Skip to content

Commit d15477b

Browse files
committed
Revert "[GVN/PRE] Hoist global values outside of loops."
There's no agreement about this patch. I personally find the PRE machinery of the current GVN hard enough to reason about that I'm not sure I'll try to land this again, instead of working on the rewrite). llvm-svn: 284796
1 parent 94bd575 commit d15477b

File tree

3 files changed

+36
-115
lines changed

3 files changed

+36
-115
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 26 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -122,84 +122,69 @@ template <> struct DenseMapInfo<GVN::Expression> {
122122
/// location of the instruction from which it was formed.
123123
struct llvm::gvn::AvailableValue {
124124
enum ValType {
125-
SimpleVal, // A simple offsetted value that is accessed.
126-
LoadVal, // A value produced by a load.
127-
MemIntrinVal, // A memory intrinsic which is loaded from.
128-
UndefVal, // A UndefValue representing a value from dead block (which
129-
// is not yet physically removed from the CFG).
130-
CreateLoadVal // A duplicate load can be created higher up in the CFG that
131-
// will eliminate this one.
125+
SimpleVal, // A simple offsetted value that is accessed.
126+
LoadVal, // A value produced by a load.
127+
MemIntrin, // A memory intrinsic which is loaded from.
128+
UndefVal // A UndefValue representing a value from dead block (which
129+
// is not yet physically removed from the CFG).
132130
};
133131

134132
/// V - The value that is live out of the block.
135-
std::pair<Value *, ValType> Val;
133+
PointerIntPair<Value *, 2, ValType> Val;
136134

137135
/// Offset - The byte offset in Val that is interesting for the load query.
138136
unsigned Offset;
139137

140138
static AvailableValue get(Value *V, unsigned Offset = 0) {
141139
AvailableValue Res;
142-
Res.Val.first = V;
143-
Res.Val.second = SimpleVal;
140+
Res.Val.setPointer(V);
141+
Res.Val.setInt(SimpleVal);
144142
Res.Offset = Offset;
145143
return Res;
146144
}
147145

148146
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset = 0) {
149147
AvailableValue Res;
150-
Res.Val.first = MI;
151-
Res.Val.second = MemIntrinVal;
148+
Res.Val.setPointer(MI);
149+
Res.Val.setInt(MemIntrin);
152150
Res.Offset = Offset;
153151
return Res;
154152
}
155153

156-
static AvailableValue getCreateLoad(LoadInst *LI) {
157-
AvailableValue Res;
158-
Res.Val.first = LI;
159-
Res.Val.second = CreateLoadVal;
160-
return Res;
161-
}
162-
163154
static AvailableValue getLoad(LoadInst *LI, unsigned Offset = 0) {
164155
AvailableValue Res;
165-
Res.Val.first = LI;
166-
Res.Val.second = LoadVal;
156+
Res.Val.setPointer(LI);
157+
Res.Val.setInt(LoadVal);
167158
Res.Offset = Offset;
168159
return Res;
169160
}
170161

171162
static AvailableValue getUndef() {
172163
AvailableValue Res;
173-
Res.Val.first = nullptr;
174-
Res.Val.second = UndefVal;
164+
Res.Val.setPointer(nullptr);
165+
Res.Val.setInt(UndefVal);
175166
Res.Offset = 0;
176167
return Res;
177168
}
178169

179-
bool isSimpleValue() const { return Val.second == SimpleVal; }
180-
bool isCoercedLoadValue() const { return Val.second == LoadVal; }
181-
bool isMemIntrinValue() const { return Val.second == MemIntrinVal; }
182-
bool isUndefValue() const { return Val.second == UndefVal; }
183-
bool isCreateLoadValue() const { return Val.second == CreateLoadVal; }
184-
185-
LoadInst *getCreateLoadValue() const {
186-
assert(isCreateLoadValue() && "Wrong accessor");
187-
return cast<LoadInst>(Val.first);
188-
}
170+
bool isSimpleValue() const { return Val.getInt() == SimpleVal; }
171+
bool isCoercedLoadValue() const { return Val.getInt() == LoadVal; }
172+
bool isMemIntrinValue() const { return Val.getInt() == MemIntrin; }
173+
bool isUndefValue() const { return Val.getInt() == UndefVal; }
189174

190175
Value *getSimpleValue() const {
191176
assert(isSimpleValue() && "Wrong accessor");
192-
return Val.first;
177+
return Val.getPointer();
193178
}
194179

195180
LoadInst *getCoercedLoadValue() const {
196181
assert(isCoercedLoadValue() && "Wrong accessor");
197-
return cast<LoadInst>(Val.first);
182+
return cast<LoadInst>(Val.getPointer());
198183
}
199184

200185
MemIntrinsic *getMemIntrinValue() const {
201186
assert(isMemIntrinValue() && "Wrong accessor");
202-
return cast<MemIntrinsic>(Val.first);
187+
return cast<MemIntrinsic>(Val.getPointer());
203188
}
204189

205190
/// Emit code at the specified insertion point to adjust the value defined
@@ -1180,11 +1165,7 @@ Value *AvailableValue::MaterializeAdjustedValue(LoadInst *LI,
11801165
Value *Res;
11811166
Type *LoadTy = LI->getType();
11821167
const DataLayout &DL = LI->getModule()->getDataLayout();
1183-
if (isCreateLoadValue()) {
1184-
Instruction *I = getCreateLoadValue()->clone();
1185-
I->insertBefore(InsertPt);
1186-
Res = I;
1187-
} else if (isSimpleValue()) {
1168+
if (isSimpleValue()) {
11881169
Res = getSimpleValue();
11891170
if (Res->getType() != LoadTy) {
11901171
Res = GetStoreValueForLoad(Res, Offset, LoadTy, InsertPt, DL);
@@ -1372,7 +1353,7 @@ void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
13721353
continue;
13731354
}
13741355

1375-
if (!DepInfo.isDef() && !DepInfo.isClobber() && !DepInfo.isNonFuncLocal()) {
1356+
if (!DepInfo.isDef() && !DepInfo.isClobber()) {
13761357
UnavailableBlocks.push_back(DepBB);
13771358
continue;
13781359
}
@@ -1383,25 +1364,12 @@ void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
13831364
Value *Address = Deps[i].getAddress();
13841365

13851366
AvailableValue AV;
1386-
// TODO: We can use anything where the operands are available, and we should
1387-
// learn to recreate operands in other blocks if they are available.
1388-
// Because we don't have the infrastructure in our PRE, we restrict this to
1389-
// global values, because we know the operands are always available.
1390-
if (DepInfo.isNonFuncLocal()) {
1391-
if (isSafeToSpeculativelyExecute(LI) &&
1392-
isa<GlobalValue>(LI->getPointerOperand())) {
1393-
AV = AvailableValue::getCreateLoad(LI);
1394-
ValuesPerBlock.push_back(AvailableValueInBlock::get(
1395-
&LI->getParent()->getParent()->getEntryBlock(), std::move(AV)));
1396-
} else
1397-
UnavailableBlocks.push_back(DepBB);
1398-
1399-
} else if (AnalyzeLoadAvailability(LI, DepInfo, Address, AV)) {
1367+
if (AnalyzeLoadAvailability(LI, DepInfo, Address, AV)) {
14001368
// subtlety: because we know this was a non-local dependency, we know
14011369
// it's safe to materialize anywhere between the instruction within
14021370
// DepInfo and the end of it's block.
1403-
ValuesPerBlock.push_back(
1404-
AvailableValueInBlock::get(DepBB, std::move(AV)));
1371+
ValuesPerBlock.push_back(AvailableValueInBlock::get(DepBB,
1372+
std::move(AV)));
14051373
} else {
14061374
UnavailableBlocks.push_back(DepBB);
14071375
}

llvm/test/Transforms/GVN/PRE/hoist-loads.ll

Lines changed: 0 additions & 53 deletions
This file was deleted.

llvm/test/Transforms/GVN/PRE/pre-single-pred.ll

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
; RUN: opt < %s -gvn -enable-load-pre -S | FileCheck %s
2+
; This testcase assumed we'll PRE the load into %for.cond, but we don't actually
3+
; verify that doing so is safe. If there didn't _happen_ to be a load in
4+
; %for.end, we would actually be lengthening the execution on some paths, and
5+
; we were never actually checking that case. Now we actually do perform some
6+
; conservative checking to make sure we don't make paths longer, but we don't
7+
; currently get this case, which we got lucky on previously.
8+
;
9+
; Now that that faulty assumption is corrected, test that we DON'T incorrectly
10+
; hoist the load. Doing the right thing for the wrong reasons is still a bug.
211

312
@p = external global i32
413
define i32 @f(i32 %n) nounwind {
5-
; CHECK: entry:
6-
; CHECK-NEXT: %0 = load i32, i32* @p
714
entry:
815
br label %for.cond
916

@@ -15,9 +22,8 @@ for.cond: ; preds = %for.inc, %entry
1522
for.cond.for.end_crit_edge: ; preds = %for.cond
1623
br label %for.end
1724

18-
; The load of @p should be hoisted into the entry block.
1925
; CHECK: for.body:
20-
; CHECK-NEXT: %dec = add i32 %tmp3, -1
26+
; CHECK-NEXT: %tmp3 = load i32, i32* @p
2127
for.body: ; preds = %for.cond
2228
%tmp3 = load i32, i32* @p ; <i32> [#uses=1]
2329
%dec = add i32 %tmp3, -1 ; <i32> [#uses=2]

0 commit comments

Comments
 (0)