mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-15 07:18:33 +00:00
[CGP] Fix handling of null pointer values in optimizeMemoryInst
The current way that trivial addressing modes are detected incorrectly thinks that null pointers are non-trivial, leading to an infinite loop where we keep duplicating the same select. Fix this by aware of null when deciding if an addressing mode is trivial. Differential Revision: https://reviews.llvm.org/D40447 llvm-svn: 319019
This commit is contained in:
parent
f3c0aec971
commit
4b476488ba
@ -2080,16 +2080,14 @@ struct ExtAddrMode : public TargetLowering::AddrMode {
|
||||
return static_cast<FieldName>(Result);
|
||||
}
|
||||
|
||||
// AddrModes with a baseReg or gv where the reg/gv is
|
||||
// the only populated field are trivial.
|
||||
// An AddrMode is trivial if it involves no calculation i.e. it is just a base
|
||||
// with no offset.
|
||||
bool isTrivial() {
|
||||
if (BaseGV && !BaseOffs && !Scale && !BaseReg)
|
||||
return true;
|
||||
|
||||
if (!BaseGV && !BaseOffs && !Scale && BaseReg)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
// An AddrMode is (BaseGV + BaseReg + BaseOffs + ScaleReg * Scale) so it is
|
||||
// trivial if at most one of these terms is nonzero, except that BaseGV and
|
||||
// BaseReg both being zero actually means a null pointer value, which we
|
||||
// consider to be 'non-zero' here.
|
||||
return !BaseOffs && !Scale && !(BaseGV && BaseReg);
|
||||
}
|
||||
|
||||
Value *GetFieldAsValue(FieldName Field, Type *IntPtrTy) {
|
||||
|
@ -366,3 +366,55 @@ entey:
|
||||
store i32 %value, i32* %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Same for a select between a value and global variable
|
||||
; CHECK-LABEL: @test_select_trivial_ptr_gv
|
||||
; CHECK: select i1 %cmp, i32* %ptr, i32* @gv2
|
||||
define void @test_select_trivial_ptr_gv(i32* %ptr, i32 %value) {
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%select = select i1 %cmp, i32* %ptr, i32* @gv2
|
||||
store i32 %value, i32* %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Same for a select between a global variable and null, though the test needs to
|
||||
; be a little more complicated to avoid dereferencing a potential null pointer
|
||||
; CHECK-LABEL: @test_select_trivial_gv_null
|
||||
; CHECK: select i1 %cmp.i, i32* @gv1, i32* null
|
||||
define void @test_select_trivial_gv_null(){
|
||||
entry:
|
||||
%gv1_val = load i32, i32* @gv1, align 4
|
||||
%cmp.i = icmp eq i32 %gv1_val, 0
|
||||
%spec.select.i = select i1 %cmp.i, i32* @gv1, i32* null
|
||||
br i1 %cmp.i, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%val = load i32, i32* %spec.select.i, align 4
|
||||
%inc = add nsw i32 %val, 1
|
||||
store i32 %inc, i32* %spec.select.i, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Same for a select between a value and null
|
||||
; CHECK-LABEL: @test_select_trivial_ptr_null
|
||||
; CHECK: select i1 %cmp.i, i32* %ptr, i32* null
|
||||
define void @test_select_trivial_ptr_null(i32* %ptr){
|
||||
entry:
|
||||
%gv1_val = load i32, i32* %ptr, align 4
|
||||
%cmp.i = icmp eq i32 %gv1_val, 0
|
||||
%spec.select.i = select i1 %cmp.i, i32* %ptr, i32* null
|
||||
br i1 %cmp.i, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%val = load i32, i32* %spec.select.i, align 4
|
||||
%inc = add nsw i32 %val, 1
|
||||
store i32 %inc, i32* %spec.select.i, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user