Skip to content

Commit 949ec83

Browse files
authored
[InstCombine] Relax the same-underlying-object constraint for the GEP canonicalization (#76583)
7d7001b canonicalizes `(gep i8, X, (ptrtoint Y) - (ptrtoint X))` into `bitcast Y` iff `X` and `Y` have the same underlying object. I find that the result of this pattern is usually used as an operand of an icmp in some real-world applications. I think we can do the canonicalization if the result is only used by icmps/ptrtoints. Alive2: https://alive2.llvm.org/ce/z/j4-HJZ
1 parent c313d0d commit 949ec83

File tree

2 files changed

+94
-4
lines changed

2 files changed

+94
-4
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2471,14 +2471,26 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
24712471

24722472
if (TyAllocSize == 1) {
24732473
// Canonicalize (gep i8* X, (ptrtoint Y)-(ptrtoint X)) to (bitcast Y),
2474-
// but only if both point to the same underlying object (otherwise
2475-
// provenance is not necessarily retained).
2474+
// but only if the result pointer is only used as if it were an integer,
2475+
// or both point to the same underlying object (otherwise provenance is
2476+
// not necessarily retained).
24762477
Value *X = GEP.getPointerOperand();
24772478
Value *Y;
24782479
if (match(GEP.getOperand(1),
24792480
m_Sub(m_PtrToInt(m_Value(Y)), m_PtrToInt(m_Specific(X)))) &&
2480-
getUnderlyingObject(X) == getUnderlyingObject(Y))
2481-
return CastInst::CreatePointerBitCastOrAddrSpaceCast(Y, GEPType);
2481+
GEPType == Y->getType()) {
2482+
bool HasSameUnderlyingObject =
2483+
getUnderlyingObject(X) == getUnderlyingObject(Y);
2484+
bool Changed = false;
2485+
GEP.replaceUsesWithIf(Y, [&](Use &U) {
2486+
bool ShouldReplace = HasSameUnderlyingObject ||
2487+
isa<ICmpInst>(U.getUser()) ||
2488+
isa<PtrToIntInst>(U.getUser());
2489+
Changed |= ShouldReplace;
2490+
return ShouldReplace;
2491+
});
2492+
return Changed ? &GEP : nullptr;
2493+
}
24822494
} else {
24832495
// Canonicalize (gep T* X, V / sizeof(T)) to (gep i8* X, V)
24842496
Value *V;

llvm/test/Transforms/InstCombine/getelementptr.ll

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,4 +1537,82 @@ define ptr @gep_ashr_without_exact(ptr %p, i64 %off) {
15371537
ret ptr %ptr
15381538
}
15391539

1540+
define i1 @test_only_used_by_icmp(ptr %a, ptr %b, ptr %c) {
1541+
; CHECK-LABEL: @test_only_used_by_icmp(
1542+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1543+
; CHECK-NEXT: ret i1 [[CMP]]
1544+
;
1545+
%pa = ptrtoint ptr %a to i64
1546+
%pb = ptrtoint ptr %b to i64
1547+
%sub = sub i64 %pb, %pa
1548+
%gep = getelementptr i8, ptr %a, i64 %sub
1549+
%cmp = icmp eq ptr %gep, %c
1550+
ret i1 %cmp
1551+
}
1552+
1553+
define i64 @test_only_used_by_ptrtoint(ptr %a, ptr %b) {
1554+
; CHECK-LABEL: @test_only_used_by_ptrtoint(
1555+
; CHECK-NEXT: [[VAL:%.*]] = ptrtoint ptr [[B:%.*]] to i64
1556+
; CHECK-NEXT: ret i64 [[VAL]]
1557+
;
1558+
%pa = ptrtoint ptr %a to i64
1559+
%pb = ptrtoint ptr %b to i64
1560+
%sub = sub i64 %pb, %pa
1561+
%gep = getelementptr i8, ptr %a, i64 %sub
1562+
%val = ptrtoint ptr %gep to i64
1563+
ret i64 %val
1564+
}
1565+
1566+
define i64 @test_used_by_both(ptr %a, ptr %b, ptr %c) {
1567+
; CHECK-LABEL: @test_used_by_both(
1568+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1569+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1570+
; CHECK: if.then:
1571+
; CHECK-NEXT: [[VAL:%.*]] = ptrtoint ptr [[B]] to i64
1572+
; CHECK-NEXT: ret i64 [[VAL]]
1573+
; CHECK: if.else:
1574+
; CHECK-NEXT: ret i64 0
1575+
;
1576+
%pa = ptrtoint ptr %a to i64
1577+
%pb = ptrtoint ptr %b to i64
1578+
%sub = sub i64 %pb, %pa
1579+
%gep = getelementptr i8, ptr %a, i64 %sub
1580+
%cmp = icmp eq ptr %gep, %c
1581+
br i1 %cmp, label %if.then, label %if.else
1582+
if.then:
1583+
%val = ptrtoint ptr %gep to i64
1584+
ret i64 %val
1585+
if.else:
1586+
ret i64 0
1587+
}
1588+
1589+
; Negative tests
1590+
1591+
define i64 @test_used_by_both_invalid(ptr %a, ptr %b, ptr %c) {
1592+
; CHECK-LABEL: @test_used_by_both_invalid(
1593+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
1594+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1595+
; CHECK: if.then:
1596+
; CHECK-NEXT: [[PB:%.*]] = ptrtoint ptr [[B]] to i64
1597+
; CHECK-NEXT: [[PA:%.*]] = ptrtoint ptr [[A:%.*]] to i64
1598+
; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PB]], [[PA]]
1599+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[SUB]]
1600+
; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[GEP]], align 8
1601+
; CHECK-NEXT: ret i64 [[VAL]]
1602+
; CHECK: if.else:
1603+
; CHECK-NEXT: ret i64 0
1604+
;
1605+
%pa = ptrtoint ptr %a to i64
1606+
%pb = ptrtoint ptr %b to i64
1607+
%sub = sub i64 %pb, %pa
1608+
%gep = getelementptr i8, ptr %a, i64 %sub
1609+
%cmp = icmp eq ptr %gep, %c
1610+
br i1 %cmp, label %if.then, label %if.else
1611+
if.then:
1612+
%val = load i64, ptr %gep, align 8
1613+
ret i64 %val
1614+
if.else:
1615+
ret i64 0
1616+
}
1617+
15401618
!0 = !{!"branch_weights", i32 2, i32 10}

0 commit comments

Comments
 (0)