Skip to content

Commit 10223c7

Browse files
committed
[ConstraintElim] Use nusw flag for GEP decomposition
Check for nusw instead of inbounds when decomposing GEPs. In this particular case, we can also look through multiple nusw flags, because we will ultimately be working in the unsigned constraint system.
1 parent a7fda0e commit 10223c7

File tree

2 files changed

+70
-5
lines changed

2 files changed

+70
-5
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,12 @@ struct OffsetResult {
387387
Value *BasePtr;
388388
APInt ConstantOffset;
389389
SmallMapVector<Value *, APInt, 4> VariableOffsets;
390-
bool AllInbounds;
390+
GEPNoWrapFlags NW;
391391

392392
OffsetResult() : BasePtr(nullptr), ConstantOffset(0, uint64_t(0)) {}
393393

394394
OffsetResult(GEPOperator &GEP, const DataLayout &DL)
395-
: BasePtr(GEP.getPointerOperand()), AllInbounds(GEP.isInBounds()) {
395+
: BasePtr(GEP.getPointerOperand()), NW(GEP.getNoWrapFlags()) {
396396
ConstantOffset = APInt(DL.getIndexTypeSizeInBits(BasePtr->getType()), 0);
397397
}
398398
};
@@ -426,7 +426,7 @@ static OffsetResult collectOffsets(GEPOperator &GEP, const DataLayout &DL) {
426426
Result.ConstantOffset += ConstantOffset2;
427427
if (Result.VariableOffsets.size() == 0 && VariableOffsets2.size() == 1)
428428
Result.VariableOffsets = VariableOffsets2;
429-
Result.AllInbounds &= InnerGEP->isInBounds();
429+
Result.NW &= InnerGEP->getNoWrapFlags();
430430
}
431431
return Result;
432432
}
@@ -450,9 +450,9 @@ static Decomposition decomposeGEP(GEPOperator &GEP,
450450

451451
assert(!IsSigned && "The logic below only supports decomposition for "
452452
"unsigned predicates at the moment.");
453-
const auto &[BasePtr, ConstantOffset, VariableOffsets, AllInbounds] =
453+
const auto &[BasePtr, ConstantOffset, VariableOffsets, NW] =
454454
collectOffsets(GEP, DL);
455-
if (!BasePtr || !AllInbounds)
455+
if (!BasePtr || !NW.hasNoUnsignedSignedWrap())
456456
return &GEP;
457457

458458
Decomposition Result(ConstantOffset.getSExtValue(), DecompEntry(1, BasePtr));

llvm/test/Transforms/ConstraintElimination/gep-arithmetic.ll

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,68 @@ ptr.check:
630630
exit:
631631
ret i4 3
632632
}
633+
634+
define i1 @test_nusw(ptr %p, i32 %x, i32 %y) {
635+
; CHECK-LABEL: @test_nusw(
636+
; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64
637+
; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64
638+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]]
639+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]])
640+
; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]]
641+
; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]]
642+
; CHECK-NEXT: ret i1 true
643+
;
644+
%x.ext = zext i32 %x to i64
645+
%y.ext = zext i32 %y to i64
646+
%cmp1 = icmp ugt i64 %x.ext, %y.ext
647+
call void @llvm.assume(i1 %cmp1)
648+
%gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext
649+
%gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext
650+
%cmp2 = icmp ugt ptr %gep.x, %gep.y
651+
ret i1 %cmp2
652+
}
653+
654+
define i1 @test_nusw_nested(ptr %p, i32 %x, i32 %y) {
655+
; CHECK-LABEL: @test_nusw_nested(
656+
; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64
657+
; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64
658+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]]
659+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]])
660+
; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]]
661+
; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr nusw i8, ptr [[GEP_X]], i64 1
662+
; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]]
663+
; CHECK-NEXT: ret i1 true
664+
;
665+
%x.ext = zext i32 %x to i64
666+
%y.ext = zext i32 %y to i64
667+
%cmp1 = icmp ugt i64 %x.ext, %y.ext
668+
call void @llvm.assume(i1 %cmp1)
669+
%gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext
670+
%gep.x1 = getelementptr nusw i8, ptr %gep.x, i64 1
671+
%gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext
672+
%cmp2 = icmp ugt ptr %gep.x1, %gep.y
673+
ret i1 %cmp2
674+
}
675+
676+
define i1 @test_missing_nusw(ptr %p, i32 %x, i32 %y) {
677+
; CHECK-LABEL: @test_missing_nusw(
678+
; CHECK-NEXT: [[X_EXT:%.*]] = zext i32 [[X:%.*]] to i64
679+
; CHECK-NEXT: [[Y_EXT:%.*]] = zext i32 [[Y:%.*]] to i64
680+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[X_EXT]], [[Y_EXT]]
681+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]])
682+
; CHECK-NEXT: [[GEP_X:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 [[X_EXT]]
683+
; CHECK-NEXT: [[GEP_X1:%.*]] = getelementptr i8, ptr [[GEP_X]], i64 1
684+
; CHECK-NEXT: [[GEP_Y:%.*]] = getelementptr nusw i8, ptr [[P]], i64 [[Y_EXT]]
685+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt ptr [[GEP_X1]], [[GEP_Y]]
686+
; CHECK-NEXT: ret i1 [[CMP2]]
687+
;
688+
%x.ext = zext i32 %x to i64
689+
%y.ext = zext i32 %y to i64
690+
%cmp1 = icmp ugt i64 %x.ext, %y.ext
691+
call void @llvm.assume(i1 %cmp1)
692+
%gep.x = getelementptr nusw i8, ptr %p, i64 %x.ext
693+
%gep.x1 = getelementptr i8, ptr %gep.x, i64 1
694+
%gep.y = getelementptr nusw i8, ptr %p, i64 %y.ext
695+
%cmp2 = icmp ugt ptr %gep.x1, %gep.y
696+
ret i1 %cmp2
697+
}

0 commit comments

Comments
 (0)