[llvm] ee605b0 - [ConstraintElim] Use collectOffset result for chained gep support.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 1 09:01:26 PST 2022
Author: Florian Hahn
Date: 2022-12-01T17:01:07Z
New Revision: ee605b0acccea92bb2375921955008e1d6ca22d2
URL: https://github.com/llvm/llvm-project/commit/ee605b0acccea92bb2375921955008e1d6ca22d2
DIFF: https://github.com/llvm/llvm-project/commit/ee605b0acccea92bb2375921955008e1d6ca22d2.diff
LOG: [ConstraintElim] Use collectOffset result for chained gep support.
This slightly simplifies the code and addresses a correctness issue
where the index scaling for the precondition was not considered
properly.
Thanks to @nikic for pointing that out in D137840.
Added:
Modified:
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
llvm/test/Transforms/ConstraintElimination/gep-add-multiple-indices.ll
llvm/test/Transforms/ConstraintElimination/gep-sub.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index f823a38ca14b0..dd0abe223afab 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -243,40 +243,36 @@ decomposeGEP(GetElementPtrInst &GEP,
if (!GEP.isInBounds())
return &GEP;
+ Type *PtrTy = GEP.getType()->getScalarType();
+ unsigned BitWidth = DL.getIndexTypeSizeInBits(PtrTy);
+ MapVector<Value *, APInt> VariableOffsets;
+ APInt ConstantOffset(BitWidth, 0);
+ if (!GEP.collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset))
+ return &GEP;
+
// Handle the (gep (gep ....), C) case by incrementing the constant
// coefficient of the inner GEP, if C is a constant.
auto *InnerGEP = dyn_cast<GetElementPtrInst>(GEP.getPointerOperand());
- if (InnerGEP && GEP.getNumOperands() == 2 &&
- isa<ConstantInt>(GEP.getOperand(1))) {
- APInt Offset = cast<ConstantInt>(GEP.getOperand(1))->getValue();
+ if (VariableOffsets.empty() && InnerGEP && InnerGEP->getNumOperands() == 2) {
auto Result = decompose(InnerGEP, Preconditions, IsSigned, DL);
+ Result.add(ConstantOffset.getSExtValue());
- auto GTI = gep_type_begin(GEP);
- // Bail out for scalable vectors for now.
- if (isa<ScalableVectorType>(GTI.getIndexedType()))
- return &GEP;
- int64_t Scale = static_cast<int64_t>(
- DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize());
-
- Result.add(multiplyWithOverflow(Scale, Offset.getSExtValue()));
- if (Offset.isNegative()) {
+ if (ConstantOffset.isNegative()) {
+ unsigned Scale = DL.getTypeAllocSize(InnerGEP->getResultElementType());
+ int64_t ConstantOffsetI = ConstantOffset.getSExtValue();
+ if (ConstantOffsetI % Scale != 0)
+ return &GEP;
// Add pre-condition ensuring the GEP is increasing monotonically and
// can be de-composed.
+ // Both sides are normalized by being divided by Scale.
Preconditions.emplace_back(
CmpInst::ICMP_SGE, InnerGEP->getOperand(1),
ConstantInt::get(InnerGEP->getOperand(1)->getType(),
- -1 * Offset.getSExtValue()));
+ -1 * (ConstantOffsetI / Scale)));
}
return Result;
}
- Type *PtrTy = GEP.getType()->getScalarType();
- unsigned BitWidth = DL.getIndexTypeSizeInBits(PtrTy);
- MapVector<Value *, APInt> VariableOffsets;
- APInt ConstantOffset(BitWidth, 0);
- if (!GEP.collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset))
- return &GEP;
-
Decomposition Result(ConstantOffset.getSExtValue(),
DecompEntry(1, GEP.getPointerOperand()));
for (auto [Index, Scale] : VariableOffsets) {
diff --git a/llvm/test/Transforms/ConstraintElimination/gep-add-multiple-indices.ll b/llvm/test/Transforms/ConstraintElimination/gep-add-multiple-indices.ll
index c85841b4c68d2..ef899c5c8282a 100644
--- a/llvm/test/Transforms/ConstraintElimination/gep-add-multiple-indices.ll
+++ b/llvm/test/Transforms/ConstraintElimination/gep-add-multiple-indices.ll
@@ -9,7 +9,7 @@ define i1 @test_outer_gep_last_index_no_overflow_all_inbounds_1(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST_0]], i64 1, i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 [[C_1]]
+; CHECK-NEXT: ret i1 true
;
%dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0
%upper = getelementptr inbounds ptr, ptr %dst, i64 2
@@ -24,7 +24,7 @@ define i1 @test_outer_gep_last_index_no_overflow_all_inbounds_2(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i64 3
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST_0]], i64 1, i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 [[C_1]]
+; CHECK-NEXT: ret i1 true
;
%dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0
%upper = getelementptr inbounds ptr, ptr %dst, i64 3
@@ -39,7 +39,7 @@ define i1 @test_outer_gep_last_index_overflow_all_inbounds(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST_0]], i64 1, i64 2
; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0
%upper = getelementptr inbounds ptr, ptr %dst, i64 2
@@ -54,7 +54,7 @@ define i1 @test_inner_gep_multiple_indices_ult_true_all_inbounds(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST]], i64 0, i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: ret i1 [[C]]
;
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 0
%upper = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 2
@@ -69,7 +69,7 @@ define i1 @test_inner_gep_multiple_indices_uge_true_all_inbounds(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST]], i64 0, i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C:%.*]] = icmp uge ptr [[GEP_1]], [[DST_0]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: ret i1 [[C]]
;
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 0
%upper = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 2
@@ -85,7 +85,7 @@ define i1 @test_inner_gep_multiple_indices_ult_false_all_inbounds(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST]], i64 0, i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 2
; CHECK-NEXT: [[C:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: ret i1 [[C]]
;
entry:
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 0
@@ -102,7 +102,7 @@ define i1 @test_inner_gep_multiple_indices_uge_true_all_inbounds_2(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST]], i64 0, i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 2
; CHECK-NEXT: [[C:%.*]] = icmp uge ptr [[GEP_1]], [[DST_0]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: ret i1 [[C]]
;
entry:
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 0
@@ -203,7 +203,7 @@ define i1 @test_inner_gep_multi_index(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[DST_0]], i64 1, i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 [[C_1]]
+; CHECK-NEXT: ret i1 true
;
%dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0
%upper = getelementptr inbounds ptr, ptr %dst, i64 2
@@ -233,7 +233,7 @@ define i1 @test_inner_gep_multi_index_no_overflow_all_inbounds_1(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: ret i1 [[C_1]]
;
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 0, i64 1
%upper = getelementptr inbounds i32, ptr %dst, i64 2
@@ -248,7 +248,7 @@ define i1 @test_inner_gep_multi_index_no_overflow_all_inbounds_2(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: ret i1 [[C_1]]
;
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 1, i64 0
%upper = getelementptr inbounds i32, ptr %dst, i64 2
@@ -263,7 +263,7 @@ define i1 @test_inner_gep_multi_index_no_overflow_all_inbounds_3(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: ret i1 [[C_1]]
;
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 1, i64 0
%upper = getelementptr inbounds i32, ptr %dst, i64 3
@@ -278,7 +278,7 @@ define i1 @test_inner_gep_multi_index_no_overflow_all_inbounds_4(ptr %dst) {
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 4
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: ret i1 [[C_1]]
;
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 1, i64 0
%upper = getelementptr inbounds i32, ptr %dst, i64 4
@@ -294,7 +294,7 @@ define i1 @test_inner_gep_multi_index_no_overflow_all_inbounds_5(i64 %off, ptr %
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 5
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ule ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 true
+; CHECK-NEXT: ret i1 [[C_1]]
;
%off.ult = icmp ule i64 %off, 2
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 2, i64 0
@@ -311,7 +311,7 @@ define i1 @test_inner_gep_multi_index_no_overflow_all_inbounds_6(i64 %off, ptr %
; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 5
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, ptr [[DST_0]], i64 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[GEP_1]], [[UPPER]]
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: ret i1 [[C_1]]
;
%off.ult = icmp ule i64 %off, 2
%dst.0 = getelementptr inbounds [2 x i32], ptr %dst, i64 2, i64 0
diff --git a/llvm/test/Transforms/ConstraintElimination/gep-sub.ll b/llvm/test/Transforms/ConstraintElimination/gep-sub.ll
index be83e7b91a4d7..b499e280c1e37 100644
--- a/llvm/test/Transforms/ConstraintElimination/gep-sub.ll
+++ b/llvm/test/Transforms/ConstraintElimination/gep-sub.ll
@@ -529,7 +529,7 @@ define i1 @gep_i16_sub_1_uge_inbounds(ptr %dst, ptr %lower) {
; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp ule ptr [[DST_SUB_1]], [[LOWER]]
; CHECK-NEXT: [[DST_SUB_2:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -2
; CHECK-NEXT: [[CMP_SUB_2:%.*]] = icmp ule ptr [[DST_SUB_2]], [[DST]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 false, true
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 false, [[CMP_SUB_2]]
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i16, ptr [[DST_ADD_3]], i64 -3
; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp ule ptr [[DST_SUB_3]], [[LOWER]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_3]]
More information about the llvm-commits
mailing list