diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h index dba4b6d4c0ad..e0b68a390278 100644 --- a/llvm/include/llvm/CodeGen/FastISel.h +++ b/llvm/include/llvm/CodeGen/FastISel.h @@ -343,6 +343,8 @@ private: bool SelectCast(const User *I, unsigned Opcode); + bool SelectExtractValue(const User *I); + /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. /// Emit code to ensure constants are copied into registers when needed. /// Remember the virtual registers that need to be added to the Machine PHI diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 2f5adcc55656..27e4d01784b1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -44,6 +44,7 @@ #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Operator.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -838,6 +839,44 @@ FastISel::SelectFNeg(const User *I) { return true; } +bool +FastISel::SelectExtractValue(const User *U) { + const ExtractValueInst *EVI = dyn_cast(U); + if (!U) + return false; + + // Make sure we only try to handle extracts with a legal result. + EVT RealVT = TLI.getValueType(EVI->getType(), /*AllowUnknown=*/true); + if (!RealVT.isSimple()) + return false; + MVT VT = RealVT.getSimpleVT(); + if (!TLI.isTypeLegal(VT)) + return false; + + const Value *Op0 = EVI->getOperand(0); + const Type *AggTy = Op0->getType(); + + // Get the base result register. + unsigned ResultReg; + DenseMap::iterator I = FuncInfo.ValueMap.find(Op0); + if (I != FuncInfo.ValueMap.end()) + ResultReg = I->second; + else + ResultReg = FuncInfo.InitializeRegForValue(Op0); + + // Get the actual result register, which is an offset from the base register. + unsigned VTIndex = ComputeLinearIndex(AggTy, EVI->idx_begin(), EVI->idx_end()); + + SmallVector AggValueVTs; + ComputeValueVTs(TLI, AggTy, AggValueVTs); + + for (unsigned i = 0; i < VTIndex; i++) + ResultReg += TLI.getNumRegisters(FuncInfo.Fn->getContext(), AggValueVTs[i]); + + UpdateValueMap(EVI, ResultReg); + return true; +} + bool FastISel::SelectOperator(const User *I, unsigned Opcode) { switch (Opcode) { @@ -942,6 +981,9 @@ FastISel::SelectOperator(const User *I, unsigned Opcode) { return true; } + case Instruction::ExtractValue: + return SelectExtractValue(I); + case Instruction::PHI: llvm_unreachable("FastISel shouldn't visit PHI nodes!"); diff --git a/llvm/test/CodeGen/X86/fast-isel-extract.ll b/llvm/test/CodeGen/X86/fast-isel-extract.ll new file mode 100644 index 000000000000..5493fbf9e110 --- /dev/null +++ b/llvm/test/CodeGen/X86/fast-isel-extract.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -mtriple x86_64-apple-darwin11 -O0 | FileCheck %s + +%struct.x = type { i64, i64 } +declare %struct.x @f() + +define void @test1(i64*) nounwind ssp { + %2 = tail call %struct.x @f() nounwind + %3 = extractvalue %struct.x %2, 0 + %4 = add i64 %3, 10 + store i64 %4, i64* %0 + ret void +; CHECK: test1: +; CHECK: callq _f +; CHECK-NEXT: addq $10, %rax +} + +define void @test2(i64*) nounwind ssp { + %2 = tail call %struct.x @f() nounwind + %3 = extractvalue %struct.x %2, 1 + %4 = add i64 %3, 10 + store i64 %4, i64* %0 + ret void +; CHECK: test2: +; CHECK: callq _f +; CHECK-NEXT: addq $10, %rdx +}