forked from OSchip/llvm-project
[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:
parent
9d20eaf9c0
commit
b552e16b0b
|
@ -495,12 +495,15 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr,
|
||||||
if (!AreEquivalentAddressValues(StorePtr, Ptr))
|
if (!AreEquivalentAddressValues(StorePtr, Ptr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
if (IsLoadCSE)
|
||||||
|
*IsLoadCSE = false;
|
||||||
|
|
||||||
Value *Val = SI->getValueOperand();
|
Value *Val = SI->getValueOperand();
|
||||||
if (CastInst::isBitOrNoopPointerCastable(Val->getType(), AccessTy, DL)) {
|
if (CastInst::isBitOrNoopPointerCastable(Val->getType(), AccessTy, DL))
|
||||||
if (IsLoadCSE)
|
|
||||||
*IsLoadCSE = false;
|
|
||||||
return Val;
|
return Val;
|
||||||
}
|
|
||||||
|
if (auto *C = dyn_cast<Constant>(Val))
|
||||||
|
return ConstantFoldLoadThroughBitcast(C, AccessTy, DL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -22,8 +22,7 @@ define i32 @vec_store_load_first(i32* %p) {
|
||||||
; CHECK-LABEL: @vec_store_load_first(
|
; CHECK-LABEL: @vec_store_load_first(
|
||||||
; CHECK-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>*
|
; 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: 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 1
|
||||||
; CHECK-NEXT: ret i32 [[LOAD]]
|
|
||||||
;
|
;
|
||||||
%p2 = bitcast i32* %p to <2 x i32>*
|
%p2 = bitcast i32* %p to <2 x i32>*
|
||||||
store <2 x i32> <i32 1, i32 2>, <2 x i32>* %p2
|
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
|
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) {
|
define i32 @vec_store_load_second(i32* %p) {
|
||||||
; CHECK-LABEL: @vec_store_load_second(
|
; CHECK-LABEL: @vec_store_load_second(
|
||||||
; CHECK-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>*
|
; CHECK-NEXT: [[P2:%.*]] = bitcast i32* [[P:%.*]] to <2 x i32>*
|
||||||
|
|
Loading…
Reference in New Issue