Skip to content

Commit a73db81

Browse files
committed
Fix incorrect codegen with respect to GEPs #85333
As mentioned in #68882 and https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699 Gep arithmetic isn't consistent with different types. GVNSink didn't realize this and sank all geps as long as their operands can be wired via PHIs in a post-dominator. Fixes: #85333
1 parent fefac5d commit a73db81

File tree

2 files changed

+111
-8
lines changed

2 files changed

+111
-8
lines changed

llvm/lib/Transforms/Scalar/GVNSink.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -719,21 +719,22 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI,
719719
// try and continue making progress.
720720
Instruction *I0 = NewInsts[0];
721721

722-
// If all instructions that are going to participate don't have the same
723-
// number of operands, we can't do any useful PHI analysis for all operands.
724-
auto hasDifferentNumOperands = [&I0](Instruction *I) {
725-
return I->getNumOperands() != I0->getNumOperands();
722+
auto hasDifferentOperands = [&I0](Instruction *I) {
723+
return !I0->isSameOperationAs(I);
726724
};
727-
if (any_of(NewInsts, hasDifferentNumOperands))
725+
726+
if (any_of(NewInsts, hasDifferentOperands))
728727
return std::nullopt;
729728

730729
for (unsigned OpNum = 0, E = I0->getNumOperands(); OpNum != E; ++OpNum) {
731730
ModelledPHI PHI(NewInsts, OpNum, ActivePreds);
732731
if (PHI.areAllIncomingValuesSame())
733732
continue;
734-
if (!canReplaceOperandWithVariable(I0, OpNum))
735-
// We can 't create a PHI from this instruction!
736-
return std::nullopt;
733+
for (auto &Candidate : NewInsts) {
734+
if (!canReplaceOperandWithVariable(Candidate, OpNum))
735+
// We can 't create a PHI from this instruction!
736+
return std::nullopt;
737+
}
737738
if (NeededPHIs.count(PHI))
738739
continue;
739740
if (!PHI.areAllIncomingValuesSameType())
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt -passes=gvn-sink -S %s | FileCheck %s
3+
4+
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
5+
target triple = "thumbv7em-none-unknown-eabi"
6+
7+
%"struct.std::pair" = type <{ i32, %struct.substruct, [2 x i8] }>
8+
%struct.substruct = type { i8, i8 }
9+
%"struct.std::random_access_iterator_tag" = type { i8 }
10+
11+
; Check that gep is not sunk as they are of different types.
12+
define void @bar(ptr noundef nonnull align 4 dereferenceable(4) %__i, i32 noundef %__n) {
13+
; CHECK-LABEL: define void @bar(
14+
; CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[__I:%.*]], i32 noundef [[__N:%.*]]) {
15+
; CHECK-NEXT: entry:
16+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[__N]], 1
17+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
18+
; CHECK: if.then:
19+
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__I]], align 4
20+
; CHECK-NEXT: [[INCDEC_PTR4:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 -8
21+
; CHECK-NEXT: br label [[IF_END6:%.*]]
22+
; CHECK: if.else:
23+
; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__I]], align 4
24+
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds %"struct.std::pair", ptr [[TMP1]], i32 [[__N]]
25+
; CHECK-NEXT: br label [[IF_END6]]
26+
; CHECK: if.end6:
27+
; CHECK-NEXT: [[INCDEC_PTR_SINK:%.*]] = phi ptr [ [[INCDEC_PTR4]], [[IF_THEN]] ], [ [[ADD_PTR]], [[IF_ELSE]] ]
28+
; CHECK-NEXT: store ptr [[INCDEC_PTR_SINK]], ptr [[__I]], align 4
29+
; CHECK-NEXT: ret void
30+
;
31+
entry:
32+
%cmp = icmp eq i32 %__n, 1
33+
br i1 %cmp, label %if.then, label %if.else
34+
35+
if.then:
36+
%3 = load ptr, ptr %__i, align 4
37+
%incdec.ptr4 = getelementptr inbounds i8, ptr %3, i32 -8
38+
br label %if.end6
39+
40+
if.else:
41+
%4 = load ptr, ptr %__i, align 4
42+
%add.ptr = getelementptr inbounds %"struct.std::pair", ptr %4, i32 %__n
43+
br label %if.end6
44+
45+
if.end6:
46+
%incdec.ptr.sink = phi ptr [ %incdec.ptr4, %if.then ], [ %add.ptr, %if.else ]
47+
store ptr %incdec.ptr.sink, ptr %__i, align 4
48+
ret void
49+
}
50+
51+
; Check that load,gep, and store are all sunk as they are safe to do.
52+
define void @foo(ptr noundef nonnull align 4 dereferenceable(4) %__i, i32 noundef %__n) {
53+
; CHECK-LABEL: define void @foo(
54+
; CHECK-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[__I:%.*]], i32 noundef [[__N:%.*]]) {
55+
; CHECK-NEXT: entry:
56+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[__N]], 1
57+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
58+
; CHECK: if.then:
59+
; CHECK-NEXT: br label [[IF_END6:%.*]]
60+
; CHECK: if.else:
61+
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[__N]], -1
62+
; CHECK-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE5:%.*]]
63+
; CHECK: if.then3:
64+
; CHECK-NEXT: br label [[IF_END6]]
65+
; CHECK: if.else5:
66+
; CHECK-NEXT: br label [[IF_END6]]
67+
; CHECK: if.end6:
68+
; CHECK-NEXT: [[DOTSINK1:%.*]] = phi i32 [ 8, [[IF_THEN]] ], [ -8, [[IF_THEN3]] ], [ -4, [[IF_ELSE5]] ]
69+
; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__I]], align 4
70+
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 [[DOTSINK1]]
71+
; CHECK-NEXT: store ptr [[INCDEC_PTR]], ptr [[__I]], align 4
72+
; CHECK-NEXT: ret void
73+
;
74+
entry:
75+
%cmp = icmp eq i32 %__n, 1
76+
br i1 %cmp, label %if.then, label %if.else
77+
78+
if.then:
79+
%1 = load ptr, ptr %__i, align 4
80+
%incdec.ptr = getelementptr inbounds i8, ptr %1, i32 8
81+
store ptr %incdec.ptr, ptr %__i, align 4
82+
br label %if.end6
83+
84+
if.else:
85+
%cmp2 = icmp eq i32 %__n, -1
86+
br i1 %cmp2, label %if.then3, label %if.else5
87+
88+
if.then3:
89+
%3 = load ptr, ptr %__i, align 4
90+
%incdec.ptr4 = getelementptr inbounds i8, ptr %3, i32 -8
91+
store ptr %incdec.ptr4, ptr %__i, align 4
92+
br label %if.end6
93+
94+
if.else5:
95+
%4 = load ptr, ptr %__i, align 4
96+
%add.ptr = getelementptr inbounds i8, ptr %4, i32 -4
97+
store ptr %add.ptr, ptr %__i, align 4
98+
br label %if.end6
99+
100+
if.end6:
101+
ret void
102+
}

0 commit comments

Comments
 (0)