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 goes down the type heirarchy to perform the checks. 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/Target/LLVMIR/Import/verify-gep.ll =================================================================== --- /dev/null +++ mlir/test/Target/LLVMIR/Import/verify-gep.ll @@ -0,0 +1,10 @@ +; RUN: mlir-translate --import-llvm %s | FileCheck %s + +%sub_struct = type { i32, i8 } +%my_struct = type { %sub_struct, [4 x i32] } + +define void @foo(%my_struct* %arg, i32 %idx) { + ; CHECK: llvm.getelementptr %arg0 + %1 = getelementptr %my_struct, %my_struct* %arg, i32 0, i32 1, i32 %idx + ret void +}