From 2586b8f9366aed5a1efa44d3f18d095511601642 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 16 May 2011 20:27:46 +0000 Subject: [PATCH] Basic fast-isel of extractvalue. Not too helpful on its own, given the IR clang generates for cases like this, but it should become more useful soon. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131417 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/FastISel.h | 2 ++ lib/CodeGen/SelectionDAG/FastISel.cpp | 42 +++++++++++++++++++++++++++ test/CodeGen/X86/fast-isel-extract.ll | 26 +++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 test/CodeGen/X86/fast-isel-extract.ll diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index dba4b6d4c0a..e0b68a39027 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/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/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 2f5adcc5565..27e4d01784b 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/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/test/CodeGen/X86/fast-isel-extract.ll b/test/CodeGen/X86/fast-isel-extract.ll new file mode 100644 index 00000000000..5493fbf9e11 --- /dev/null +++ b/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 +}