Index: mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp =================================================================== --- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -579,7 +579,7 @@ static const DenseMap opcMap = { // Ret is handled specially. // Br is handled specially. - // FIXME: switch + // Switch is handled specially. // FIXME: indirectbr // FIXME: invoke INST(Resume, Resume), @@ -805,6 +805,46 @@ b.create(state); return success(); } + case llvm::Instruction::Switch: { + auto *swInst = cast(inst); + // Process the condition value. + Value condition = processValue(swInst->getCondition()); + if (!condition) { + return emitError(loc) << "failed to process the condition value of " + << diag(*inst) << "\n"; + } + + SmallVector defaultBlockArgs; + // Process the default case. + llvm::BasicBlock *defaultBB = swInst->getDefaultDest(); + if (failed(processBranchArgs(swInst, defaultBB, defaultBlockArgs))) { + return emitError(loc) << "failed to process block arguments for the" + << "default case in " << diag(*inst) << "\n"; + } + + // Process the cases. + unsigned numCases = swInst->getNumCases(); + SmallVector> caseOperands(numCases); + SmallVector caseOperandRefs(numCases); + SmallVector caseValues(numCases); + SmallVector caseBlocks(numCases); + for (const auto &en : llvm::enumerate(swInst->cases())) { + const llvm::SwitchInst::CaseHandle &caseHandle = en.value(); + unsigned i = en.index(); + llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor(); + if (failed(processBranchArgs(swInst, succBB, caseOperands[i]))) { + return emitError(loc) << "failed to process block arguments for case" + << " #" << i << " in " << diag(*inst) << "\n"; + } + caseOperandRefs[i] = caseOperands[i]; + caseValues[i] = caseHandle.getCaseValue()->getSExtValue(); + caseBlocks[i] = blocks[succBB]; + } + + b.create(loc, condition, blocks[defaultBB], defaultBlockArgs, + caseValues, caseBlocks, caseOperandRefs); + return success(); + } case llvm::Instruction::PHI: { Type type = processType(inst->getType()); if (!type) Index: mlir/test/Target/LLVMIR/Import/switch.ll =================================================================== --- /dev/null +++ mlir/test/Target/LLVMIR/Import/switch.ll @@ -0,0 +1,55 @@ +; RUN: mlir-translate --import-llvm %s | FileCheck %s + +declare void @g(i32) + +; CHECK: llvm.func @f(%[[ARG:.+]]: i32) { +define void @f(i32 %val) { +; CHECK: %[[C0:.+]] = llvm.mlir.constant(11 : i32) : i32 +; CHECK: %[[C1:.+]] = llvm.mlir.constant(87 : i32) : i32 +; CHECK: %[[C2:.+]] = llvm.mlir.constant(78 : i32) : i32 +; CHECK: %[[C3:.+]] = llvm.mlir.constant(94 : i32) : i32 +; CHECK: %[[C4:.+]] = llvm.mlir.constant(1 : i32) : i32 +; CHECK: llvm.switch %[[ARG]] : i32, ^[[BB5:.+]] [ +; CHECK: 0: ^[[BB1:.+]], +; CHECK: 9: ^[[BB2:.+]], +; CHECK: 994: ^[[BB3:.+]], +; CHECK: 1154: ^[[BB4:.+]] +; CHECK: ] + switch i32 %val, label %def [ + i32 0, label %one + i32 9, label %two + i32 994, label %three + i32 1154, label %four + ] + +; CHECK: ^[[BB1]]: +; CHECK: llvm.call @g(%[[C4]]) : (i32) -> () +; CHECK: llvm.return +one: + call void @g(i32 1) + ret void +; CHECK: ^[[BB2]]: +; CHECK: llvm.call @g(%[[C3]]) : (i32) -> () +; CHECK: llvm.return +two: + call void @g(i32 94) + ret void +; CHECK: ^[[BB3]]: +; CHECK: llvm.call @g(%[[C2]]) : (i32) -> () +; CHECK: llvm.return +three: + call void @g(i32 78) + ret void +; CHECK: ^[[BB4]]: +; CHECK: llvm.call @g(%[[C1]]) : (i32) -> () +; CHECK: llvm.return +four: + call void @g(i32 87) + ret void +; CHECK: ^[[BB5]]: +; CHECK: llvm.call @g(%[[C0]]) : (i32) -> () +; CHECK: llvm.return +def: + call void @g(i32 11) + ret void +}