mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
[InstCombine] peek through bitcasted vector/array pointer GEP operand
The bitcast may be interfering with other combines or vectorization as shown in PR16739: https://bugs.llvm.org/show_bug.cgi?id=16739 Most pointer-related optimizations are probably able to look through this bitcast, but removing the bitcast shrinks the IR, so it's at least a size savings. Differential Revision: https://reviews.llvm.org/D44833 llvm-svn: 330237
This commit is contained in:
parent
f215d6d79f
commit
f5a2032ee8
@ -1945,14 +1945,34 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
||||
PtrOp = BC;
|
||||
}
|
||||
|
||||
/// See if we can simplify:
|
||||
/// X = bitcast A* to B*
|
||||
/// Y = gep X, <...constant indices...>
|
||||
/// into a gep of the original struct. This is important for SROA and alias
|
||||
/// analysis of unions. If "A" is also a bitcast, wait for A/X to be merged.
|
||||
if (auto *BCI = dyn_cast<BitCastInst>(PtrOp)) {
|
||||
Value *SrcOp = BCI->getOperand(0);
|
||||
PointerType *SrcType = cast<PointerType>(BCI->getSrcTy());
|
||||
Type *SrcEltType = SrcType->getElementType();
|
||||
|
||||
// GEP directly using the source operand if this GEP is accessing an element
|
||||
// of a bitcasted pointer to vector or array of the same dimensions:
|
||||
// gep (bitcast <c x ty>* X to [c x ty]*), Y, Z --> gep X, Y, Z
|
||||
// gep (bitcast [c x ty]* X to <c x ty>*), Y, Z --> gep X, Y, Z
|
||||
auto areMatchingArrayAndVecTypes = [](Type *ArrTy, Type *VecTy) {
|
||||
return ArrTy->getArrayElementType() == VecTy->getVectorElementType() &&
|
||||
ArrTy->getArrayNumElements() == VecTy->getVectorNumElements();
|
||||
};
|
||||
if (GEP.getNumOperands() == 3 &&
|
||||
((GEPEltType->isArrayTy() && SrcEltType->isVectorTy() &&
|
||||
areMatchingArrayAndVecTypes(GEPEltType, SrcEltType)) ||
|
||||
(GEPEltType->isVectorTy() && SrcEltType->isArrayTy() &&
|
||||
areMatchingArrayAndVecTypes(SrcEltType, GEPEltType)))) {
|
||||
GEP.setOperand(0, SrcOp);
|
||||
GEP.setSourceElementType(SrcEltType);
|
||||
return &GEP;
|
||||
}
|
||||
|
||||
// See if we can simplify:
|
||||
// X = bitcast A* to B*
|
||||
// Y = gep X, <...constant indices...>
|
||||
// into a gep of the original struct. This is important for SROA and alias
|
||||
// analysis of unions. If "A" is also a bitcast, wait for A/X to be merged.
|
||||
unsigned OffsetBits = DL.getIndexTypeSizeInBits(GEPType);
|
||||
APInt Offset(OffsetBits, 0);
|
||||
if (!isa<BitCastInst>(SrcOp) && GEP.accumulateConstantOffset(DL, Offset)) {
|
||||
|
@ -27,3 +27,23 @@ define <2 x i8*> @vectorindex3() {
|
||||
ret <2 x i8*> %1
|
||||
}
|
||||
|
||||
define i32* @bitcast_vec_to_array_gep(<7 x i32>* %x, i64 %y, i64 %z) {
|
||||
; CHECK-LABEL: @bitcast_vec_to_array_gep(
|
||||
; CHECK-NEXT: [[GEP:%.*]] = getelementptr <7 x i32>, <7 x i32>* [[X:%.*]], i64 [[Y:%.*]], i64 [[Z:%.*]]
|
||||
; CHECK-NEXT: ret i32* [[GEP]]
|
||||
;
|
||||
%arr_ptr = bitcast <7 x i32>* %x to [7 x i32]*
|
||||
%gep = getelementptr [7 x i32], [7 x i32]* %arr_ptr, i64 %y, i64 %z
|
||||
ret i32* %gep
|
||||
}
|
||||
|
||||
define i32* @bitcast_array_to_vec_gep([3 x i32]* %x, i64 %y, i64 %z) {
|
||||
; CHECK-LABEL: @bitcast_array_to_vec_gep(
|
||||
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[X:%.*]], i64 [[Y:%.*]], i64 [[Z:%.*]]
|
||||
; CHECK-NEXT: ret i32* [[GEP]]
|
||||
;
|
||||
%vec_ptr = bitcast [3 x i32]* %x to <3 x i32>*
|
||||
%gep = getelementptr inbounds <3 x i32>, <3 x i32>* %vec_ptr, i64 %y, i64 %z
|
||||
ret i32* %gep
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user