LLVM LoongArch Assertion Failure With Vector Division

by Alex Johnson 54 views

An intriguing issue has surfaced within the LLVM compiler infrastructure, specifically affecting the LoongArch backend. This article delves into an assertion failure encountered during the SelectionDAG legalization phase when dealing with vector division operations. Understanding the intricacies of this failure requires a closer examination of the code snippet that triggers it, the error message, and the context in which it occurs.

Understanding the Issue

The core problem revolves around an assertion failure that occurs during the legalization of a SelectionDAG (Directed Acyclic Graph). The SelectionDAG is an intermediate representation used by LLVM to represent the program's operations in a way that is suitable for instruction selection. Legalization is the process of transforming the DAG into a form that is legal for the target architecture.

The assertion failure, specifically, is triggered when the type of an operation is not considered legal by the target-specific lowering information (TLI). In simpler terms, the compiler encounters an operation with a data type that it doesn't know how to handle for the LoongArch architecture. This leads to the assertion failure, halting the compilation process.

Code Snippet

The code snippet provided is a minimal example that reproduces the issue:

target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "loongarch64-unknown-linux-musl"

define <16 x i16> @func_1(<16 x i16> %shuffle) {
entry:
  %div = udiv <16 x i16> %shuffle, splat (i16 3)
  ret <16 x i16> %div
}

This LLVM IR code defines a function @func_1 that takes a vector of 16 16-bit integers (<16 x i16>) as input, performs an unsigned division by 3, and returns the result. The division operation, udiv <16 x i16> %shuffle, splat (i16 3), is where the problem lies.

Error Message

The error message provides valuable information about the location and nature of the failure:

llc: /root/llvm-project/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:985: void {anonymous}::SelectionDAGLegalize::LegalizeOp(llvm::SDNode*): Assertion `(TLI.getTypeAction(*DAG.getContext(), Op.getValueType()) == TargetLowering::TypeLegal || Op.getOpcode() == ISD::TargetConstant || Op.getOpcode() == ISD::Register) && "Unexpected illegal type!"' failed.

This message indicates that the assertion failed within the LegalizeOp function in LegalizeDAG.cpp at line 985. The assertion checks whether the type of the current operation (Op.getValueType()) is legal according to the target lowering information (TLI). If the type is not legal, and the operation is not a target constant or a register, the assertion fails.

Stack Trace

The stack trace provides a call stack of the functions that were executed leading up to the assertion failure. It helps in pinpointing the exact location in the code where the error occurred. The stack trace includes functions like SelectionDAGLegalize::LegalizeOp, llvm::SelectionDAG::Legalize, and llvm::SelectionDAGISel::CodeGenAndEmitDAG, which are all part of the SelectionDAG legalization and instruction selection process.

Deep Dive into the Assertion Failure

The assertion (TLI.getTypeAction(*DAG.getContext(), Op.getValueType()) == TargetLowering::TypeLegal || Op.getOpcode() == ISD::TargetConstant || Op.getOpcode() == ISD::Register) && "Unexpected illegal type!" is designed to ensure that the compiler only attempts to generate code for operations with types that are supported by the target architecture. When this assertion fails, it indicates that the compiler has encountered an operation with an unsupported type.

In the context of the provided code snippet, the unsupported type is likely the <16 x i16> vector type when used with the unsigned division (udiv) operation. The LoongArch backend may not have complete support for vector division with this specific data type, leading to the assertion failure.

Possible Causes

Several factors could contribute to this issue:

  1. Incomplete Target Support: The LoongArch backend might not fully implement vector division for all possible data types. Certain vector sizes or element types might be missing, leading to the assertion failure when the compiler encounters them.
  2. Legalization Issues: The legalization process might not be correctly transforming the vector division operation into a sequence of lower-level operations that are supported by the target architecture. This could be due to bugs in the legalization code or missing legalization patterns.
  3. Type Lowering Problems: The target lowering information (TLI) might not be correctly classifying the <16 x i16> vector type as legal for division operations. This could be due to incorrect or incomplete TLI definitions.

Impact

This assertion failure prevents the compilation of code that uses vector division with the <16 x i16> type on the LoongArch architecture. This can limit the performance and functionality of applications that rely on vectorization for performance-critical tasks. The issue needs to be addressed to ensure that the LLVM compiler can generate efficient and correct code for LoongArch.

Reproducing the Issue

The reproducer link (https://godbolt.org/z/Px5q639q7) provides a convenient way to reproduce the issue. By compiling the code snippet on Compiler Explorer with the LoongArch target, you can observe the assertion failure and examine the generated code.

To reproduce the issue locally, you would need to:

  1. Install LLVM: Ensure that you have a recent version of LLVM installed with LoongArch support.
  2. Save the Code: Save the code snippet as a .ll file (e.g., test.ll).
  3. Compile: Use the llc command to compile the code:
llc -march=loongarch64 test.ll -o test.s

This command will attempt to compile the LLVM IR code to LoongArch assembly. If the issue is present, the compilation will fail with the assertion error.

Proposed Solutions and Workarounds

Addressing this assertion failure requires a multi-pronged approach:

  1. Implement Missing Vector Division Support: The LoongArch backend needs to be extended to fully support vector division for all relevant data types, including <16 x i16>. This might involve adding new instructions or patterns to handle vector division operations.
  2. Fix Legalization Issues: The legalization process needs to be carefully examined to ensure that vector division operations are correctly transformed into lower-level operations that are supported by the target architecture. This might involve adding new legalization patterns or fixing bugs in the existing patterns.
  3. Update Target Lowering Information: The target lowering information (TLI) needs to be updated to accurately classify the <16 x i16> vector type as legal for division operations. This might involve modifying the TLI definitions to include the necessary type information.

Potential Workarounds

While a complete fix requires changes to the LLVM compiler, there might be some temporary workarounds that can be used to mitigate the issue:

  1. Scalarization: One workaround is to scalarize the vector division operation. This involves manually splitting the vector into individual scalar elements, performing the division on each element, and then reassembling the results into a vector. This can be done using LLVM IR instructions like extractelement and insertelement.
  2. Alternative Vector Size: Another workaround is to use a different vector size or element type that is supported by the LoongArch backend. For example, you might try using <8 x i32> instead of <16 x i16>. However, this might require changes to the code and could impact performance.

Conclusion

The assertion failure in the LLVM LoongArch backend highlights the importance of complete and correct target support for vector operations. Addressing this issue will improve the performance and functionality of applications that rely on vectorization on the LoongArch architecture. By implementing missing vector division support, fixing legalization issues, and updating target lowering information, the LLVM compiler can be made to generate efficient and correct code for LoongArch.

For more in-depth information about LLVM, check out the official LLVM documentation. This is a valuable resource for developers and anyone interested in learning more about LLVM's architecture, features, and capabilities.