mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-13 23:18:51 +00:00
[InstCombine] Add optimization of redundant insertvalue instructions.
rdar://problem/11861387 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208214 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0c78010b88
commit
355e0a6460
@ -211,6 +211,7 @@ public:
|
||||
Instruction *visitStoreInst(StoreInst &SI);
|
||||
Instruction *visitBranchInst(BranchInst &BI);
|
||||
Instruction *visitSwitchInst(SwitchInst &SI);
|
||||
Instruction *visitInsertValueInst(InsertValueInst &IV);
|
||||
Instruction *visitInsertElementInst(InsertElementInst &IE);
|
||||
Instruction *visitExtractElementInst(ExtractElementInst &EI);
|
||||
Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
|
||||
|
@ -490,6 +490,42 @@ static ShuffleOps CollectShuffleElements(Value *V,
|
||||
return std::make_pair(V, nullptr);
|
||||
}
|
||||
|
||||
/// Try to find redundant insertvalue instructions, like the following ones:
|
||||
/// %0 = insertvalue { i8, i32 } undef, i8 %x, 0
|
||||
/// %1 = insertvalue { i8, i32 } %0, i8 %y, 0
|
||||
/// Here the second instruction inserts values at the same indices, as the
|
||||
/// first one, making the first one redundant.
|
||||
/// It should be transformed to:
|
||||
/// %0 = insertvalue { i8, i32 } undef, i8 %y, 0
|
||||
Instruction *InstCombiner::visitInsertValueInst(InsertValueInst &I) {
|
||||
bool IsRedundant = false;
|
||||
ArrayRef<unsigned int> FirstIndices = I.getIndices();
|
||||
|
||||
// If there is a chain of insertvalue instructions (each of them except the
|
||||
// last one has only one use and it's another insertvalue insn from this
|
||||
// chain), check if any of the 'children' uses the same indices as the first
|
||||
// instruction. In this case, the first one is redundant.
|
||||
Value *V = &I;
|
||||
unsigned int Depth = 0;
|
||||
while (V->hasOneUse() && Depth < 10) {
|
||||
User *U = V->user_back();
|
||||
InsertValueInst *UserInsInst = dyn_cast<InsertValueInst>(U);
|
||||
if (!UserInsInst || U->getType() != I.getType()) {
|
||||
break;
|
||||
}
|
||||
if (UserInsInst->getIndices() == FirstIndices) {
|
||||
IsRedundant = true;
|
||||
break;
|
||||
}
|
||||
V = UserInsInst;
|
||||
Depth++;
|
||||
}
|
||||
|
||||
if (IsRedundant)
|
||||
return ReplaceInstUsesWith(I, I.getOperand(0));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) {
|
||||
Value *VecOp = IE.getOperand(0);
|
||||
Value *ScalarOp = IE.getOperand(1);
|
||||
|
25
test/Transforms/InstCombine/OverlappingInsertvalues.ll
Normal file
25
test/Transforms/InstCombine/OverlappingInsertvalues.ll
Normal file
@ -0,0 +1,25 @@
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
; Check that we can find and remove redundant insertvalues
|
||||
; CHECK-LABEL: foo_simple
|
||||
; CHECK-NOT: i8* %x, 0
|
||||
define { i8*, i64, i32 } @foo_simple(i8* %x, i8* %y) nounwind {
|
||||
entry:
|
||||
%0 = insertvalue { i8*, i64, i32 } undef, i8* %x, 0
|
||||
%1 = insertvalue { i8*, i64, i32 } %0, i8* %y, 0
|
||||
ret { i8*, i64, i32 } %1
|
||||
}
|
||||
; Check that we can find and remove redundant nodes in insertvalues chain
|
||||
; CHECK-LABEL: foo_ovwrt_chain
|
||||
; CHECK-NOT: i64 %y, 1
|
||||
; CHECK-NOT: i32 555, 2
|
||||
define { i8*, i64, i32 } @foo_ovwrt_chain(i8* %x, i64 %y, i64 %z) nounwind {
|
||||
entry:
|
||||
%0 = insertvalue { i8*, i64, i32 } undef, i8* %x, 0
|
||||
%1 = insertvalue { i8*, i64, i32 } %0, i64 %y, 1
|
||||
%2 = insertvalue { i8*, i64, i32 } %1, i32 555, 2
|
||||
%3 = insertvalue { i8*, i64, i32 } %2, i64 %z, 1
|
||||
%4 = insertvalue { i8*, i64, i32 } %3, i32 777, 2
|
||||
ret { i8*, i64, i32 } %4
|
||||
}
|
Loading…
Reference in New Issue
Block a user