forked from OSchip/llvm-project
[InstSimplify] Don't lose inbounds when simplifying a GEP
I noticed this while working on a (ptrtoint (gep null, x)) -> x fold. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D110168
This commit is contained in:
parent
8b87c3d573
commit
05663dc146
|
@ -248,7 +248,7 @@ Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||||
const SimplifyQuery &Q);
|
const SimplifyQuery &Q);
|
||||||
|
|
||||||
/// Given operands for a GetElementPtrInst, fold the result or return null.
|
/// Given operands for a GetElementPtrInst, fold the result or return null.
|
||||||
Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
|
Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds,
|
||||||
const SimplifyQuery &Q);
|
const SimplifyQuery &Q);
|
||||||
|
|
||||||
/// Given operands for an InsertValueInst, fold the result or return null.
|
/// Given operands for an InsertValueInst, fold the result or return null.
|
||||||
|
|
|
@ -70,8 +70,8 @@ static Value *SimplifyOrInst(Value *, Value *, const SimplifyQuery &, unsigned);
|
||||||
static Value *SimplifyXorInst(Value *, Value *, const SimplifyQuery &, unsigned);
|
static Value *SimplifyXorInst(Value *, Value *, const SimplifyQuery &, unsigned);
|
||||||
static Value *SimplifyCastInst(unsigned, Value *, Type *,
|
static Value *SimplifyCastInst(unsigned, Value *, Type *,
|
||||||
const SimplifyQuery &, unsigned);
|
const SimplifyQuery &, unsigned);
|
||||||
static Value *SimplifyGEPInst(Type *, ArrayRef<Value *>, const SimplifyQuery &,
|
static Value *SimplifyGEPInst(Type *, ArrayRef<Value *>, bool,
|
||||||
unsigned);
|
const SimplifyQuery &, unsigned);
|
||||||
static Value *SimplifySelectInst(Value *, Value *, Value *,
|
static Value *SimplifySelectInst(Value *, Value *, Value *,
|
||||||
const SimplifyQuery &, unsigned);
|
const SimplifyQuery &, unsigned);
|
||||||
|
|
||||||
|
@ -3983,7 +3983,8 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
|
||||||
|
|
||||||
if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
|
||||||
return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(),
|
return PreventSelfSimplify(SimplifyGEPInst(GEP->getSourceElementType(),
|
||||||
NewOps, Q, MaxRecurse - 1));
|
NewOps, GEP->isInBounds(), Q,
|
||||||
|
MaxRecurse - 1));
|
||||||
|
|
||||||
if (isa<SelectInst>(I))
|
if (isa<SelectInst>(I))
|
||||||
return PreventSelfSimplify(
|
return PreventSelfSimplify(
|
||||||
|
@ -4328,7 +4329,7 @@ Value *llvm::SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||||
|
|
||||||
/// Given operands for an GetElementPtrInst, see if we can fold the result.
|
/// Given operands for an GetElementPtrInst, see if we can fold the result.
|
||||||
/// If not, this returns null.
|
/// If not, this returns null.
|
||||||
static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
|
static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds,
|
||||||
const SimplifyQuery &Q, unsigned) {
|
const SimplifyQuery &Q, unsigned) {
|
||||||
// The type of the GEP pointer operand.
|
// The type of the GEP pointer operand.
|
||||||
unsigned AS =
|
unsigned AS =
|
||||||
|
@ -4448,13 +4449,13 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto *CE = ConstantExpr::getGetElementPtr(SrcTy, cast<Constant>(Ops[0]),
|
auto *CE = ConstantExpr::getGetElementPtr(SrcTy, cast<Constant>(Ops[0]),
|
||||||
Ops.slice(1));
|
Ops.slice(1), InBounds);
|
||||||
return ConstantFoldConstant(CE, Q.DL);
|
return ConstantFoldConstant(CE, Q.DL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
|
Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops, bool InBounds,
|
||||||
const SimplifyQuery &Q) {
|
const SimplifyQuery &Q) {
|
||||||
return ::SimplifyGEPInst(SrcTy, Ops, Q, RecursionLimit);
|
return ::SimplifyGEPInst(SrcTy, Ops, InBounds, Q, RecursionLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given operands for an InsertValueInst, see if we can fold the result.
|
/// Given operands for an InsertValueInst, see if we can fold the result.
|
||||||
|
@ -6220,8 +6221,9 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
|
||||||
Result = SimplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q);
|
Result = SimplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q);
|
||||||
break;
|
break;
|
||||||
case Instruction::GetElementPtr: {
|
case Instruction::GetElementPtr: {
|
||||||
Result = SimplifyGEPInst(cast<GetElementPtrInst>(I)->getSourceElementType(),
|
auto *GEPI = cast<GetElementPtrInst>(I);
|
||||||
NewOps, Q);
|
Result = SimplifyGEPInst(GEPI->getSourceElementType(), NewOps,
|
||||||
|
GEPI->isInBounds(), Q);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::InsertValue: {
|
case Instruction::InsertValue: {
|
||||||
|
|
|
@ -226,8 +226,8 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB,
|
||||||
return GEP;
|
return GEP;
|
||||||
|
|
||||||
// Simplify the GEP to handle 'gep x, 0' -> x etc.
|
// Simplify the GEP to handle 'gep x, 0' -> x etc.
|
||||||
if (Value *V = SimplifyGEPInst(GEP->getSourceElementType(),
|
if (Value *V = SimplifyGEPInst(GEP->getSourceElementType(), GEPOps,
|
||||||
GEPOps, {DL, TLI, DT, AC})) {
|
GEP->isInBounds(), {DL, TLI, DT, AC})) {
|
||||||
for (unsigned i = 0, e = GEPOps.size(); i != e; ++i)
|
for (unsigned i = 0, e = GEPOps.size(); i != e; ++i)
|
||||||
RemoveInstInputs(GEPOps[i], InstInputs);
|
RemoveInstInputs(GEPOps[i], InstInputs);
|
||||||
|
|
||||||
|
|
|
@ -1855,7 +1855,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
||||||
Type *GEPType = GEP.getType();
|
Type *GEPType = GEP.getType();
|
||||||
Type *GEPEltType = GEP.getSourceElementType();
|
Type *GEPEltType = GEP.getSourceElementType();
|
||||||
bool IsGEPSrcEleScalable = isa<ScalableVectorType>(GEPEltType);
|
bool IsGEPSrcEleScalable = isa<ScalableVectorType>(GEPEltType);
|
||||||
if (Value *V = SimplifyGEPInst(GEPEltType, Ops, SQ.getWithInstruction(&GEP)))
|
if (Value *V = SimplifyGEPInst(GEPEltType, Ops, GEP.isInBounds(),
|
||||||
|
SQ.getWithInstruction(&GEP)))
|
||||||
return replaceInstUsesWith(GEP, V);
|
return replaceInstUsesWith(GEP, V);
|
||||||
|
|
||||||
// For vector geps, use the generic demanded vector support.
|
// For vector geps, use the generic demanded vector support.
|
||||||
|
|
|
@ -1194,9 +1194,10 @@ NewGVN::ExprResult NewGVN::createExpression(Instruction *I) const {
|
||||||
SimplifyCastInst(CI->getOpcode(), E->getOperand(0), CI->getType(), SQ);
|
SimplifyCastInst(CI->getOpcode(), E->getOperand(0), CI->getType(), SQ);
|
||||||
if (auto Simplified = checkExprResults(E, I, V))
|
if (auto Simplified = checkExprResults(E, I, V))
|
||||||
return Simplified;
|
return Simplified;
|
||||||
} else if (isa<GetElementPtrInst>(I)) {
|
} else if (auto *GEPI = dyn_cast<GetElementPtrInst>(I)) {
|
||||||
Value *V = SimplifyGEPInst(
|
Value *V = SimplifyGEPInst(GEPI->getSourceElementType(),
|
||||||
E->getType(), ArrayRef<Value *>(E->op_begin(), E->op_end()), SQ);
|
ArrayRef<Value *>(E->op_begin(), E->op_end()),
|
||||||
|
GEPI->isInBounds(), SQ);
|
||||||
if (auto Simplified = checkExprResults(E, I, V))
|
if (auto Simplified = checkExprResults(E, I, V))
|
||||||
return Simplified;
|
return Simplified;
|
||||||
} else if (AllConstant) {
|
} else if (AllConstant) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ entry:
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: define void @f1
|
; CHECK-LABEL: define void @f1
|
||||||
; CHECK: %1 = load i32 (i8 addrspace(4)*, i32 addrspace(1)*)*, i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)* bitcast (i8* addrspace(4)* getelementptr (%__aaa_struct, %__aaa_struct addrspace(4)* addrspacecast (%__aaa_struct addrspace(1)* @__aaa_struct_ptr to %__aaa_struct addrspace(4)*), i64 0, i32 0, i32 3) to i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)*), align 8
|
; CHECK: %1 = load i32 (i8 addrspace(4)*, i32 addrspace(1)*)*, i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)* bitcast (i8* addrspace(4)* getelementptr inbounds (%__aaa_struct, %__aaa_struct addrspace(4)* addrspacecast (%__aaa_struct addrspace(1)* @__aaa_struct_ptr to %__aaa_struct addrspace(4)*), i64 0, i32 0, i32 3) to i32 (i8 addrspace(4)*, i32 addrspace(1)*)* addrspace(4)*), align 8
|
||||||
|
|
||||||
; Function Attrs: alwaysinline nounwind
|
; Function Attrs: alwaysinline nounwind
|
||||||
define void @f1(i32 addrspace(1)*) #1 {
|
define void @f1(i32 addrspace(1)*) #1 {
|
||||||
|
|
Loading…
Reference in New Issue