Loading from null is valid outside of addrspace 0

This patches fixes a miscompile where we were assuming that loading from null is undefined and thus we could assume it doesn't happen.  This transform is perfectly legal in address space 0, but is not neccessarily legal in other address spaces.

We really should introduce a hook to control this property on a per target per address space basis.  We may be loosing valuable optimizations in some address spaces by being too conservative.

Original patch by Thomas P Raoux (submitted to llvm-commits), tests and formatting fixes by me.




git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224961 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Philip Reames 2014-12-29 22:46:21 +00:00
parent 02d187cdb9
commit 456b7b602c
2 changed files with 30 additions and 10 deletions

View File

@ -474,18 +474,18 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
}
// load (select (cond, null, P)) -> load P
if (Constant *C = dyn_cast<Constant>(SI->getOperand(1)))
if (C->isNullValue()) {
LI.setOperand(0, SI->getOperand(2));
return &LI;
}
if (isa<ConstantPointerNull>(SI->getOperand(1)) &&
LI.getPointerAddressSpace() == 0) {
LI.setOperand(0, SI->getOperand(2));
return &LI;
}
// load (select (cond, P, null)) -> load P
if (Constant *C = dyn_cast<Constant>(SI->getOperand(2)))
if (C->isNullValue()) {
LI.setOperand(0, SI->getOperand(1));
return &LI;
}
if (isa<ConstantPointerNull>(SI->getOperand(2)) &&
LI.getPointerAddressSpace() == 0) {
LI.setOperand(0, SI->getOperand(1));
return &LI;
}
}
}
return nullptr;

View File

@ -308,6 +308,26 @@ define i32 @test16(i1 %C, i32* %P) {
; CHECK: ret i32 %V
}
;; It may be legal to load from a null address in a non-zero address space
define i32 @test16_neg(i1 %C, i32 addrspace(1)* %P) {
%P2 = select i1 %C, i32 addrspace(1)* %P, i32 addrspace(1)* null
%V = load i32 addrspace(1)* %P2
ret i32 %V
; CHECK-LABEL: @test16_neg
; CHECK-NEXT: %P2 = select i1 %C, i32 addrspace(1)* %P, i32 addrspace(1)* null
; CHECK-NEXT: %V = load i32 addrspace(1)* %P2
; CHECK: ret i32 %V
}
define i32 @test16_neg2(i1 %C, i32 addrspace(1)* %P) {
%P2 = select i1 %C, i32 addrspace(1)* null, i32 addrspace(1)* %P
%V = load i32 addrspace(1)* %P2
ret i32 %V
; CHECK-LABEL: @test16_neg2
; CHECK-NEXT: %P2 = select i1 %C, i32 addrspace(1)* null, i32 addrspace(1)* %P
; CHECK-NEXT: %V = load i32 addrspace(1)* %P2
; CHECK: ret i32 %V
}
define i1 @test17(i32* %X, i1 %C) {
%R = select i1 %C, i32* %X, i32* null
%RV = icmp eq i32* %R, null