[Loads] Forward constant vector store to load of first element

InstCombine performs simple forwarding from stores to loads, but
currently only handles the case where the load and store have the
same size. This extends it to also handle a store of a constant
with a larger size followed by a load with a smaller size.

This is implemented through ConstantFoldLoadThroughBitcast() which
is fairly primitive (e.g. does not allow storing a large integer
and then loading a small one), but at least can forward the first
element of a vector store. Unfortunately it seems that we currently
don't have a generic helper for "read a constant value as a different
type", it's all tangled up with other logic in either
ConstantFolding or VNCoercion.

Differential Revision: https://reviews.llvm.org/D98114
This commit is contained in:
Nikita Popov 2021-03-06 16:10:21 +01:00
parent 9d20eaf9c0
commit b552e16b0b
2 changed files with 21 additions and 6 deletions

View File

@ -495,12 +495,15 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr,
if (!AreEquivalentAddressValues(StorePtr, Ptr))
return nullptr;
if (IsLoadCSE)
*IsLoadCSE = false;
Value *Val = SI->getValueOperand();
if (CastInst::isBitOrNoopPointerCastable(Val->getType(), AccessTy, DL)) {
if (IsLoadCSE)
*IsLoadCSE = false;
if (CastInst::isBitOrNoopPointerCastable(Val->getType(), AccessTy, DL))
return Val;
}
if (auto *C = dyn_cast<Constant>(Val))
return ConstantFoldLoadThroughBitcast(C, AccessTy, DL);
}
return nullptr;

View File

@ -22,8 +22,7 @@ define i32 @vec_store_load_first(i32* %p) {
; CHECK-LABEL: @vec_store_load_first(
; CHECK-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>*
; CHECK-NEXT: store <2 x i32> <i32 1, i32 2>, <2 x i32>* [[P2]], align 8
; CHECK-NEXT: [[LOAD:%.*]] = load i32, i32* [[P]], align 4
; CHECK-NEXT: ret i32 [[LOAD]]
; CHECK-NEXT: ret i32 1
;
%p2 = bitcast i32* %p to <2 x i32>*
store <2 x i32> <i32 1, i32 2>, <2 x i32>* %p2
@ -31,6 +30,19 @@ define i32 @vec_store_load_first(i32* %p) {
ret i32 %load
}
define i32 @vec_store_load_first_constexpr(i32* %p) {
; CHECK-LABEL: @vec_store_load_first_constexpr(
; CHECK-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>*
; CHECK-NEXT: store <2 x i32> bitcast (i64 ptrtoint (i32 (i32*)* @vec_store_load_first to i64) to <2 x i32>), <2 x i32>* [[P2]], align 8
; CHECK-NEXT: [[LOAD:%.*]] = load i32, i32* [[P]], align 4
; CHECK-NEXT: ret i32 [[LOAD]]
;
%p2 = bitcast i32* %p to <2 x i32>*
store <2 x i32> bitcast (i64 ptrtoint (i32 (i32*)* @vec_store_load_first to i64) to <2 x i32>), <2 x i32>* %p2, align 8
%load = load i32, i32* %p, align 4
ret i32 %load
}
define i32 @vec_store_load_second(i32* %p) {
; CHECK-LABEL: @vec_store_load_second(
; CHECK-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>*