Index: mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp =================================================================== --- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -501,17 +501,15 @@ // Extract the constant value from the operand and put it into the attribute // instead. APInt staticIndexValue; - bool matched = - matchPattern(indices[operandPos], m_ConstantInt(&staticIndexValue)); - (void)matched; - assert(matched && "index into a struct must be a constant"); - assert(staticIndexValue.sge(APInt::getSignedMinValue(/*numBits=*/32)) && - "struct index underflows 32-bit integer"); - assert(staticIndexValue.sle(APInt::getSignedMaxValue(/*numBits=*/32)) && - "struct index overflows 32-bit integer"); - auto staticIndex = static_cast(staticIndexValue.getSExtValue()); - updatedStructIndices[pos] = staticIndex; - operandsToErase.push_back(operandPos); + if (matchPattern(indices[operandPos], m_ConstantInt(&staticIndexValue))) { + assert(staticIndexValue.sge(APInt::getSignedMinValue(/*numBits=*/32)) && + "struct index underflows 32-bit integer"); + assert(staticIndexValue.sle(APInt::getSignedMaxValue(/*numBits=*/32)) && + "struct index overflows 32-bit integer"); + auto staticIndex = static_cast(staticIndexValue.getSExtValue()); + updatedStructIndices[pos] = staticIndex; + operandsToErase.push_back(operandPos); + } } for (unsigned i = 0, e = indices.size(); i < e; ++i) { @@ -591,9 +589,13 @@ continue; int32_t staticIndex = structIndices.getValues()[index]; + // `findKnownStructIndices` merely tells you `index` _might_ be + // a struct index. So it's totally possible that `staticIndex` + // is still dynamic. + // FIXME: We probably should use LLVM's way to verify GEP indices, + // which recursively follows through the GEP index values. if (staticIndex == LLVM::GEPOp::kDynamicIndex) - return emitOpError() << "expected index " << index - << " indexing a struct to be constant"; + continue; if (staticIndex < 0 || static_cast(staticIndex) >= structSizes[i]) return emitOpError() << "index " << index << " indexing a struct is out of bounds"; Index: mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp =================================================================== --- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -1012,7 +1012,8 @@ llvm::enumerate(llvm::drop_begin(gep->operand_values()))) { llvm::Value *operand = en.value(); if (llvm::find(staticIndexPositions, en.index()) == - staticIndexPositions.end()) { + staticIndexPositions.end() || + !isa(operand)) { staticIndices.push_back(GEPOp::kDynamicIndex); dynamicIndices.push_back(processValue(operand)); if (!dynamicIndices.back()) Index: mlir/test/Dialect/LLVMIR/dynamic-gep-index.mlir =================================================================== --- /dev/null +++ mlir/test/Dialect/LLVMIR/dynamic-gep-index.mlir @@ -0,0 +1,12 @@ +// RUN: mlir-opt %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>, #dlti.dl_entry : vector<2xi32>>>} { + // CHECK: llvm.func @foo(%[[ARG0:.+]]: !llvm.ptr>, %[[ARG1:.+]]: i32) + llvm.func @foo(%arg0: !llvm.ptr, array<4 x i32>)>>, %arg1: i32) { + // CHECK: %[[C0:.+]] = llvm.mlir.constant(0 : i32) + %0 = llvm.mlir.constant(0 : i32) : i32 + // CHECK: llvm.getelementptr %[[ARG0]][%[[C0]], 1, %[[ARG1]]] + %1 = "llvm.getelementptr"(%arg0, %0, %arg1) {structIndices = dense<[-2147483648, 1, -2147483648]> : tensor<3xi32>} : (!llvm.ptr, array<4 x i32>)>>, i32, i32) -> !llvm.ptr + llvm.return + } +} Index: mlir/test/Target/LLVMIR/Import/dynamic-gep-index.ll =================================================================== --- /dev/null +++ mlir/test/Target/LLVMIR/Import/dynamic-gep-index.ll @@ -0,0 +1,12 @@ +; RUN: mlir-translate --import-llvm %s | FileCheck %s + +%sub_struct = type { i32, i8 } +%my_struct = type { %sub_struct, [4 x i32] } + +; CHECK: llvm.func @foo(%[[ARG0:.+]]: !llvm.ptr>, %[[ARG1:.+]]: i32) +define void @foo(%my_struct* %arg, i32 %idx) { + ; CHECK: %[[C0:.+]] = llvm.mlir.constant(0 : i32) + ; CHECK: llvm.getelementptr %[[ARG0]][%[[C0]], 1, %[[ARG1]]] + %1 = getelementptr %my_struct, %my_struct* %arg, i32 0, i32 1, i32 %idx + ret void +}