forked from OSchip/llvm-project
[InstCombine] Check type compatibility in indexed load fold
This fold could use a rewrite to an offset-based implementation, but for now make sure it doesn't crash with opaque pointers.
This commit is contained in:
parent
9474c3009e
commit
e714b98fff
|
@ -105,10 +105,14 @@ static bool isSignTest(ICmpInst::Predicate &Pred, const APInt &C) {
|
||||||
///
|
///
|
||||||
/// If AndCst is non-null, then the loaded value is masked with that constant
|
/// If AndCst is non-null, then the loaded value is masked with that constant
|
||||||
/// before doing the comparison. This handles cases like "A[i]&4 == 0".
|
/// before doing the comparison. This handles cases like "A[i]&4 == 0".
|
||||||
Instruction *
|
Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
|
||||||
InstCombinerImpl::foldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP,
|
LoadInst *LI, GetElementPtrInst *GEP, GlobalVariable *GV, CmpInst &ICI,
|
||||||
GlobalVariable *GV, CmpInst &ICI,
|
ConstantInt *AndCst) {
|
||||||
ConstantInt *AndCst) {
|
if (LI->isVolatile() || LI->getType() != GEP->getResultElementType() ||
|
||||||
|
GV->getValueType() != GEP->getSourceElementType() ||
|
||||||
|
!GV->isConstant() || !GV->hasDefinitiveInitializer())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
Constant *Init = GV->getInitializer();
|
Constant *Init = GV->getInitializer();
|
||||||
if (!isa<ConstantArray>(Init) && !isa<ConstantDataArray>(Init))
|
if (!isa<ConstantArray>(Init) && !isa<ConstantDataArray>(Init))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1865,15 +1869,13 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp,
|
||||||
// Try to optimize things like "A[i] & 42 == 0" to index computations.
|
// Try to optimize things like "A[i] & 42 == 0" to index computations.
|
||||||
Value *X = And->getOperand(0);
|
Value *X = And->getOperand(0);
|
||||||
Value *Y = And->getOperand(1);
|
Value *Y = And->getOperand(1);
|
||||||
if (auto *LI = dyn_cast<LoadInst>(X))
|
if (auto *C2 = dyn_cast<ConstantInt>(Y))
|
||||||
if (auto *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0)))
|
if (auto *LI = dyn_cast<LoadInst>(X))
|
||||||
if (auto *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0)))
|
||||||
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
|
if (auto *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
||||||
!LI->isVolatile() && isa<ConstantInt>(Y)) {
|
if (Instruction *Res =
|
||||||
ConstantInt *C2 = cast<ConstantInt>(Y);
|
foldCmpLoadFromIndexedGlobal(LI, GEP, GV, Cmp, C2))
|
||||||
if (Instruction *Res = foldCmpLoadFromIndexedGlobal(GEP, GV, Cmp, C2))
|
|
||||||
return Res;
|
return Res;
|
||||||
}
|
|
||||||
|
|
||||||
if (!Cmp.isEquality())
|
if (!Cmp.isEquality())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -3476,13 +3478,11 @@ Instruction *InstCombinerImpl::foldICmpInstWithConstantNotInt(ICmpInst &I) {
|
||||||
case Instruction::Load:
|
case Instruction::Load:
|
||||||
// Try to optimize things like "A[i] > 4" to index computations.
|
// Try to optimize things like "A[i] > 4" to index computations.
|
||||||
if (GetElementPtrInst *GEP =
|
if (GetElementPtrInst *GEP =
|
||||||
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0))) {
|
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0)))
|
||||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
||||||
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
|
if (Instruction *Res =
|
||||||
!cast<LoadInst>(LHSI)->isVolatile())
|
foldCmpLoadFromIndexedGlobal(cast<LoadInst>(LHSI), GEP, GV, I))
|
||||||
if (Instruction *Res = foldCmpLoadFromIndexedGlobal(GEP, GV, I))
|
return Res;
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6632,10 +6632,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
|
||||||
case Instruction::Load:
|
case Instruction::Load:
|
||||||
if (auto *GEP = dyn_cast<GetElementPtrInst>(LHSI->getOperand(0)))
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(LHSI->getOperand(0)))
|
||||||
if (auto *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
if (auto *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
||||||
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
|
if (Instruction *Res = foldCmpLoadFromIndexedGlobal(
|
||||||
!cast<LoadInst>(LHSI)->isVolatile())
|
cast<LoadInst>(LHSI), GEP, GV, I))
|
||||||
if (Instruction *Res = foldCmpLoadFromIndexedGlobal(GEP, GV, I))
|
return Res;
|
||||||
return Res;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,7 +652,8 @@ public:
|
||||||
ICmpInst::Predicate Cond, Instruction &I);
|
ICmpInst::Predicate Cond, Instruction &I);
|
||||||
Instruction *foldAllocaCmp(ICmpInst &ICI, const AllocaInst *Alloca,
|
Instruction *foldAllocaCmp(ICmpInst &ICI, const AllocaInst *Alloca,
|
||||||
const Value *Other);
|
const Value *Other);
|
||||||
Instruction *foldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP,
|
Instruction *foldCmpLoadFromIndexedGlobal(LoadInst *LI,
|
||||||
|
GetElementPtrInst *GEP,
|
||||||
GlobalVariable *GV, CmpInst &ICI,
|
GlobalVariable *GV, CmpInst &ICI,
|
||||||
ConstantInt *AndCst = nullptr);
|
ConstantInt *AndCst = nullptr);
|
||||||
Instruction *foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI,
|
Instruction *foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI,
|
||||||
|
|
|
@ -305,3 +305,42 @@ define i1 @cmp_gep_same_base_different_type(ptr %ptr, i64 %idx1, i64 %idx2) {
|
||||||
%cmp = icmp ult ptr %gep1, %gep2
|
%cmp = icmp ult ptr %gep1, %gep2
|
||||||
ret i1 %cmp
|
ret i1 %cmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ary = constant [4 x i8] [i8 1, i8 2, i8 3, i8 4]
|
||||||
|
|
||||||
|
define i1 @cmp_load_gep_global(i64 %idx) {
|
||||||
|
; CHECK-LABEL: @cmp_load_gep_global(
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[IDX:%.*]], 2
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%gep = getelementptr [4 x i8], ptr @ary, i64 0, i64 %idx
|
||||||
|
%load = load i8, ptr %gep
|
||||||
|
%cmp = icmp eq i8 %load, 3
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_load_gep_global_different_load_type(i64 %idx) {
|
||||||
|
; CHECK-LABEL: @cmp_load_gep_global_different_load_type(
|
||||||
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr [4 x i8], ptr @ary, i64 0, i64 [[IDX:%.*]]
|
||||||
|
; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 3
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%gep = getelementptr [4 x i8], ptr @ary, i64 0, i64 %idx
|
||||||
|
%load = load i16, ptr %gep
|
||||||
|
%cmp = icmp eq i16 %load, 3
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_load_gep_global_different_gep_type(i64 %idx) {
|
||||||
|
; CHECK-LABEL: @cmp_load_gep_global_different_gep_type(
|
||||||
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr [4 x i16], ptr @ary, i64 0, i64 [[IDX:%.*]]
|
||||||
|
; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 3
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%gep = getelementptr [4 x i16], ptr @ary, i64 0, i64 %idx
|
||||||
|
%load = load i16, ptr %gep
|
||||||
|
%cmp = icmp eq i16 %load, 3
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue