}
static bool canSimplifyNullStoreOrGEP(StoreInst &SI) {
- return isa<ConstantPointerNull>(SI.getPointerOperand()) &&
- !NullPointerIsDefined(SI.getFunction(), SI.getPointerAddressSpace());
+ if (NullPointerIsDefined(SI.getFunction(), SI.getPointerAddressSpace()))
+ return false;
+
+ auto *Ptr = SI.getPointerOperand();
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Ptr))
+ if (GEPI->isInBounds())
+ Ptr = GEPI->getOperand(0);
+ return (isa<ConstantPointerNull>(Ptr) &&
+ !NullPointerIsDefined(SI.getFunction(), SI.getPointerAddressSpace()));
}
static bool canSimplifyNullLoadOrGEP(LoadInst &LI, Value *Op) {
- return isa<UndefValue>(Op) ||
- (isa<ConstantPointerNull>(Op) &&
- !NullPointerIsDefined(LI.getFunction(), LI.getPointerAddressSpace()));
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Op)) {
+ const Value *GEPI0 = GEPI->getOperand(0);
+ if (isa<ConstantPointerNull>(GEPI0) && GEPI->isInBounds() &&
+ !NullPointerIsDefined(LI.getFunction(), GEPI->getPointerAddressSpace()))
+ return true;
+ }
+ if (isa<UndefValue>(Op) ||
+ (isa<ConstantPointerNull>(Op) &&
+ !NullPointerIsDefined(LI.getFunction(), LI.getPointerAddressSpace())))
+ return true;
+ return false;
}
Instruction *InstCombinerImpl::visitLoadInst(LoadInst &LI) {
Value *PtrOp = GEP.getOperand(0);
- // The only pointer that is inbounds of null is null.
- if (isa<ConstantPointerNull>(PtrOp) && GEP.isInBounds() &&
- !NullPointerIsDefined(GEP.getFunction(),
- PtrOp->getType()->getPointerAddressSpace()))
- if (auto *PtrTy = dyn_cast<PointerType>(GEPType))
- return replaceInstUsesWith(GEP, ConstantPointerNull::get(PtrTy));
-
// Eliminate unneeded casts for indices, and replace indices which displace
// by multiples of a zero size type with zero.
bool MadeChange = false;
define i8* @gep_null_inbounds(i64 %idx) {
; CHECK-LABEL: @gep_null_inbounds(
-; CHECK-NEXT: ret i8* null
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* null, i64 [[IDX:%.*]]
+; CHECK-NEXT: ret i8* [[GEP]]
;
%gep = getelementptr inbounds i8, i8* null, i64 %idx
ret i8* %gep
define i8* @gep_null_inbounds_different_type(i64 %idx1, i64 %idx2) {
; CHECK-LABEL: @gep_null_inbounds_different_type(
-; CHECK-NEXT: ret i8* null
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [0 x i8], [0 x i8]* null, i64 0, i64 [[IDX2:%.*]]
+; CHECK-NEXT: ret i8* [[GEP]]
;
%gep = getelementptr inbounds [0 x i8], [0 x i8]* null, i64 %idx1, i64 %idx2
ret i8* %gep
define void @store_at_gep_off_null_inbounds(i64 %offset) {
; CHECK-LABEL: @store_at_gep_off_null_inbounds(
-; CHECK-NEXT: store i32 undef, i32* null, align 536870912
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, i32* null, i64 [[OFFSET:%.*]]
+; CHECK-NEXT: store i32 undef, i32* [[PTR]], align 4
; CHECK-NEXT: ret void
;
%ptr = getelementptr inbounds i32, i32 *null, i64 %offset