aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/FastISel.h2
-rw-r--r--lib/CodeGen/SelectionDAG/FastISel.cpp42
-rw-r--r--test/CodeGen/X86/fast-isel-extract.ll26
3 files changed, 70 insertions, 0 deletions
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index dba4b6d4c0..e0b68a3902 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 2f5adcc556..27e4d01784 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"
@@ -839,6 +840,44 @@ FastISel::SelectFNeg(const User *I) {
}
bool
+FastISel::SelectExtractValue(const User *U) {
+ const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(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<const Value *, unsigned>::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<EVT, 4> 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) {
case Instruction::Add:
@@ -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 0000000000..5493fbf9e1
--- /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
+}