llvm.org GIT mirror llvm / 2244b2d
Revert rL305578. There is still some buildbot failure to be fixed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305603 91177308-0d34-0410-b5e6-96231b3b80d8 Wei Mi 2 years ago
5 changed file(s) with 34 addition(s) and 321 deletion(s). Raw diff Collapse all Expand all
6767 class ValueTable {
6868 DenseMap valueNumbering;
6969 DenseMap expressionNumbering;
70
71 // Expressions is the vector of Expression. ExprIdx is the mapping from
72 // value number to the index of Expression in Expressions. We use it
73 // instead of a DenseMap because filling such mapping is faster than
74 // filling a DenseMap and the compile time is a little better.
75 uint32_t nextExprNumber;
76 std::vector Expressions;
77 std::vector ExprIdx;
78 // Value number to PHINode mapping. Used for phi-translate in scalarpre.
79 DenseMap NumberingPhi;
80 // Cache for phi-translate in scalarpre.
81 typedef DenseMap, uint32_t>
82 PhiTranslateMap;
83 PhiTranslateMap PhiTranslateTable;
84
8570 AliasAnalysis *AA;
8671 MemoryDependenceResults *MD;
8772 DominatorTree *DT;
9378 Value *LHS, Value *RHS);
9479 Expression createExtractvalueExpr(ExtractValueInst *EI);
9580 uint32_t lookupOrAddCall(CallInst *C);
96 uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
97 uint32_t Num, GVN &Gvn);
98 std::pair assignExpNewValueNum(Expression &exp);
99 bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
10081
10182 public:
10283 ValueTable();
10586 ~ValueTable();
10687
10788 uint32_t lookupOrAdd(Value *V);
108 uint32_t lookup(Value *V, bool Verify = true) const;
89 uint32_t lookup(Value *V) const;
10990 uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
11091 Value *LHS, Value *RHS);
111 uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
112 uint32_t Num, GVN &Gvn);
11392 bool exists(Value *V) const;
11493 void add(Value *V, uint32_t num);
11594 void clear();
150129 // to the remaining instructions in the block.
151130 SmallMapVector ReplaceWithConstMap;
152131 SmallVector InstrsToErase;
153
154 // Map the block to reversed postorder traversal number. It is used to
155 // find back edge easily.
156 DenseMap BlockRPONumber;
157132
158133 typedef SmallVector LoadDepVect;
159134 typedef SmallVector AvailValInBlkVect;
238213 bool performPRE(Function &F);
239214 bool performScalarPRE(Instruction *I);
240215 bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
241 BasicBlock *Curr, unsigned int ValNo);
216 unsigned int ValNo);
242217 Value *findLeader(const BasicBlock *BB, uint32_t num);
243218 void cleanupGlobalSets();
244219 void verifyRemoved(const Instruction *I) const;
250225 bool processFoldableCondBr(BranchInst *BI);
251226 void addDeadBlock(BasicBlock *BB);
252227 void assignValNumForDeadCode();
253 void assignBlockRPONumber(Function &F);
254228 };
255229
256230 /// Create a legacy GVN pass. This also allows parameterizing whether or not
7979 struct llvm::GVN::Expression {
8080 uint32_t opcode;
8181 Type *type;
82 bool commutative;
8382 SmallVector varargs;
8483
85 Expression(uint32_t o = ~2U) : opcode(o), commutative(false) {}
84 Expression(uint32_t o = ~2U) : opcode(o) {}
8685
8786 bool operator==(const Expression &other) const {
8887 if (opcode != other.opcode)
246245 assert(I->getNumOperands() == 2 && "Unsupported commutative instruction!");
247246 if (e.varargs[0] > e.varargs[1])
248247 std::swap(e.varargs[0], e.varargs[1]);
249 e.commutative = true;
250248 }
251249
252250 if (CmpInst *C = dyn_cast(I)) {
257255 Predicate = CmpInst::getSwappedPredicate(Predicate);
258256 }
259257 e.opcode = (C->getOpcode() << 8) | Predicate;
260 e.commutative = true;
261258 } else if (InsertValueInst *E = dyn_cast(I)) {
262259 for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end();
263260 II != IE; ++II)
283280 Predicate = CmpInst::getSwappedPredicate(Predicate);
284281 }
285282 e.opcode = (Opcode << 8) | Predicate;
286 e.commutative = true;
287283 return e;
288284 }
289285
351347 /// add - Insert a value into the table with a specified value number.
352348 void GVN::ValueTable::add(Value *V, uint32_t num) {
353349 valueNumbering.insert(std::make_pair(V, num));
354 if (PHINode *PN = dyn_cast(V))
355 NumberingPhi[num] = PN;
356350 }
357351
358352 uint32_t GVN::ValueTable::lookupOrAddCall(CallInst *C) {
359353 if (AA->doesNotAccessMemory(C)) {
360354 Expression exp = createExpr(C);
361 uint32_t e = assignExpNewValueNum(exp).first;
355 uint32_t &e = expressionNumbering[exp];
356 if (!e) e = nextValueNumber++;
362357 valueNumbering[C] = e;
363358 return e;
364359 } else if (AA->onlyReadsMemory(C)) {
365360 Expression exp = createExpr(C);
366 auto ValNum = assignExpNewValueNum(exp);
367 if (ValNum.second) {
368 valueNumbering[C] = ValNum.first;
369 return ValNum.first;
361 uint32_t &e = expressionNumbering[exp];
362 if (!e) {
363 e = nextValueNumber++;
364 valueNumbering[C] = e;
365 return e;
370366 }
371367 if (!MD) {
372 uint32_t e = assignExpNewValueNum(exp).first;
368 e = nextValueNumber++;
373369 valueNumbering[C] = e;
374370 return e;
375371 }
525521 case Instruction::ExtractValue:
526522 exp = createExtractvalueExpr(cast(I));
527523 break;
528 case Instruction::PHI:
529 valueNumbering[V] = nextValueNumber;
530 NumberingPhi[nextValueNumber] = cast(V);
531 return nextValueNumber++;
532524 default:
533525 valueNumbering[V] = nextValueNumber;
534526 return nextValueNumber++;
535527 }
536528
537 uint32_t e = assignExpNewValueNum(exp).first;
529 uint32_t& e = expressionNumbering[exp];
530 if (!e) e = nextValueNumber++;
538531 valueNumbering[V] = e;
539532 return e;
540533 }
541534
542535 /// Returns the value number of the specified value. Fails if
543536 /// the value has not yet been numbered.
544 uint32_t GVN::ValueTable::lookup(Value *V, bool Verify) const {
537 uint32_t GVN::ValueTable::lookup(Value *V) const {
545538 DenseMap::const_iterator VI = valueNumbering.find(V);
546 if (Verify) {
547 assert(VI != valueNumbering.end() && "Value not numbered?");
548 return VI->second;
549 }
550 return (VI != valueNumbering.end()) ? VI->second : 0;
539 assert(VI != valueNumbering.end() && "Value not numbered?");
540 return VI->second;
551541 }
552542
553543 /// Returns the value number of the given comparison,
558548 CmpInst::Predicate Predicate,
559549 Value *LHS, Value *RHS) {
560550 Expression exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
561 return assignExpNewValueNum(exp).first;
551 uint32_t& e = expressionNumbering[exp];
552 if (!e) e = nextValueNumber++;
553 return e;
562554 }
563555
564556 /// Remove all entries from the ValueTable.
565557 void GVN::ValueTable::clear() {
566558 valueNumbering.clear();
567559 expressionNumbering.clear();
568 NumberingPhi.clear();
569 PhiTranslateTable.clear();
570560 nextValueNumber = 1;
571 Expressions.clear();
572 ExprIdx.clear();
573 nextExprNumber = 0;
574561 }
575562
576563 /// Remove a value from the value numbering.
577564 void GVN::ValueTable::erase(Value *V) {
578 uint32_t Num = valueNumbering.lookup(V);
579565 valueNumbering.erase(V);
580 // If V is PHINode, V <--> value number is an one-to-one mapping.
581 if (isa(V))
582 NumberingPhi.erase(Num);
583566 }
584567
585568 /// verifyRemoved - Verify that the value is removed from all internal data
14671450 return false;
14681451 }
14691452
1470 /// Return a pair the first field showing the value number of \p Exp and the
1471 /// second field showing whether it is a value number newly created.
1472 std::pair
1473 GVN::ValueTable::assignExpNewValueNum(Expression &Exp) {
1474 uint32_t &e = expressionNumbering[Exp];
1475 bool CreateNewValNum = !e;
1476 if (CreateNewValNum) {
1477 Expressions.push_back(Exp);
1478 if (ExprIdx.size() < nextValueNumber + 1)
1479 ExprIdx.resize(nextValueNumber * 2);
1480 e = nextValueNumber;
1481 ExprIdx[nextValueNumber++] = nextExprNumber++;
1482 }
1483 return {e, CreateNewValNum};
1484 }
1485
1486 /// Return whether all the values related with the same \p num are
1487 /// defined in \p BB.
1488 bool GVN::ValueTable::areAllValsInBB(uint32_t Num, const BasicBlock *BB,
1489 GVN &Gvn) {
1490 LeaderTableEntry *Vals = &Gvn.LeaderTable[Num];
1491 while (Vals && Vals->BB == BB)
1492 Vals = Vals->Next;
1493 return !Vals;
1494 }
1495
1496 /// Wrap phiTranslateImpl to provide caching functionality.
1497 uint32_t GVN::ValueTable::phiTranslate(const BasicBlock *Pred,
1498 const BasicBlock *PhiBlock, uint32_t Num,
1499 GVN &Gvn) {
1500 auto FindRes = PhiTranslateTable.find({Num, Pred});
1501 if (FindRes != PhiTranslateTable.end())
1502 return FindRes->second;
1503 uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, Gvn);
1504 PhiTranslateTable.insert({{Num, Pred}, NewNum});
1505 return NewNum;
1506 }
1507
1508 /// Translate value number \p Num using phis, so that it has the values of
1509 /// the phis in BB.
1510 uint32_t GVN::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
1511 const BasicBlock *PhiBlock,
1512 uint32_t Num, GVN &Gvn) {
1513 if (PHINode *PN = NumberingPhi[Num]) {
1514 for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) {
1515 if (PN->getParent() == PhiBlock && PN->getIncomingBlock(i) == Pred)
1516 if (uint32_t TransVal = lookup(PN->getIncomingValue(i), false))
1517 return TransVal;
1518 }
1519 return Num;
1520 }
1521
1522 // If there is any value related with Num is defined in a BB other than
1523 // PhiBlock, it cannot depend on a phi in PhiBlock without going through
1524 // a backedge. We can do an early exit in that case to save compile time.
1525 if (!areAllValsInBB(Num, PhiBlock, Gvn))
1526 return Num;
1527
1528 if (ExprIdx[Num] == 0 || Num >= ExprIdx.size())
1529 return Num;
1530 Expression Exp = Expressions[ExprIdx[Num]];
1531
1532 for (unsigned i = 0; i < Exp.varargs.size(); i++) {
1533 // For InsertValue and ExtractValue, some varargs are index numbers
1534 // instead of value numbers. Those index numbers should not be
1535 // translated.
1536 if ((i > 1 && Exp.opcode == Instruction::InsertValue) ||
1537 (i > 0 && Exp.opcode == Instruction::ExtractValue))
1538 continue;
1539 Exp.varargs[i] = phiTranslate(Pred, PhiBlock, Exp.varargs[i], Gvn);
1540 }
1541
1542 if (Exp.commutative) {
1543 assert(Exp.varargs.size() == 2 && "Unsupported commutative expression!");
1544 if (Exp.varargs[0] > Exp.varargs[1]) {
1545 std::swap(Exp.varargs[0], Exp.varargs[1]);
1546 uint32_t Opcode = Exp.opcode >> 8;
1547 if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
1548 Exp.opcode = (Opcode << 8) |
1549 CmpInst::getSwappedPredicate(
1550 static_cast(Exp.opcode & 255));
1551 }
1552 }
1553
1554 if (uint32_t NewNum = expressionNumbering[Exp])
1555 return NewNum;
1556 return Num;
1557 }
1558
15591453 // In order to find a leader for a given value number at a
15601454 // specific basic block, we first obtain the list of all Values for that number,
15611455 // and then scan the list to find one whose block dominates the block in
15991493 "No edge between these basic blocks!");
16001494 return Pred != nullptr;
16011495 }
1602
1603
1604 void GVN::assignBlockRPONumber(Function &F) {
1605 uint32_t NextBlockNumber = 1;
1606 ReversePostOrderTraversal RPOT(&F);
1607 for (BasicBlock *BB : RPOT)
1608 BlockRPONumber[BB] = NextBlockNumber++;
1609 }
1610
16111496
16121497 // Tries to replace instruction with const, using information from
16131498 // ReplaceWithConstMap.
19701855 // Fabricate val-num for dead-code in order to suppress assertion in
19711856 // performPRE().
19721857 assignValNumForDeadCode();
1973 assignBlockRPONumber(F);
19741858 bool PREChanged = true;
19751859 while (PREChanged) {
19761860 PREChanged = performPRE(F);
20421926
20431927 // Instantiate an expression in a predecessor that lacked it.
20441928 bool GVN::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
2045 BasicBlock *Curr, unsigned int ValNo) {
1929 unsigned int ValNo) {
20461930 // Because we are going top-down through the block, all value numbers
20471931 // will be available in the predecessor by the time we need them. Any
20481932 // that weren't originally present will have been instantiated earlier
20601944 success = false;
20611945 break;
20621946 }
2063 uint32_t TValNo =
2064 VN.phiTranslate(Pred, Curr, VN.lookup(Op), *this);
2065 if (Value *V = findLeader(Pred, TValNo)) {
1947 if (Value *V = findLeader(Pred, VN.lookup(Op))) {
20661948 Instr->setOperand(i, V);
20671949 } else {
20681950 success = false;
20791961 Instr->insertBefore(Pred->getTerminator());
20801962 Instr->setName(Instr->getName() + ".pre");
20811963 Instr->setDebugLoc(Instr->getDebugLoc());
2082
2083 unsigned Num = VN.lookupOrAdd(Instr);
2084 VN.add(Instr, Num);
1964 VN.add(Instr, ValNo);
20851965
20861966 // Update the availability map to include the new instruction.
2087 addToLeaderTable(Num, Instr, Pred);
1967 addToLeaderTable(ValNo, Instr, Pred);
20881968 return true;
20891969 }
20901970
21222002
21232003 SmallVector, 8> predMap;
21242004 for (BasicBlock *P : predecessors(CurrentBlock)) {
2125 // We're not interested in PRE where blocks with predecessors that are
2126 // not reachable.
2127 if (!DT->isReachableFromEntry(P)) {
2005 // We're not interested in PRE where the block is its
2006 // own predecessor, or in blocks with predecessors
2007 // that are not reachable.
2008 if (P == CurrentBlock) {
21282009 NumWithout = 2;
21292010 break;
2130 }
2131 // It is not safe to do PRE when P->CurrentBlock is a loop backedge, and
2132 // when CurInst has operand defined in CurrentBlock (so it may be defined
2133 // by phi in the loop header).
2134 if (BlockRPONumber[P] >= BlockRPONumber[CurrentBlock] &&
2135 any_of(CurInst->operands(), [&](const Use &U) {
2136 if (auto *Inst = dyn_cast(U.get()))
2137 return Inst->getParent() == CurrentBlock;
2138 return false;
2139 })) {
2011 } else if (!DT->isReachableFromEntry(P)) {
21402012 NumWithout = 2;
21412013 break;
21422014 }
21432015
2144 uint32_t TValNo = VN.phiTranslate(P, CurrentBlock, ValNo, *this);
2145 Value *predV = findLeader(P, TValNo);
2016 Value *predV = findLeader(P, ValNo);
21462017 if (!predV) {
21472018 predMap.push_back(std::make_pair(static_cast(nullptr), P));
21482019 PREPred = P;
21822053 }
21832054 // We need to insert somewhere, so let's give it a shot
21842055 PREInstr = CurInst->clone();
2185 if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
2056 if (!performScalarPREInsertion(PREInstr, PREPred, ValNo)) {
21862057 // If we failed insertion, make sure we remove the instruction.
21872058 DEBUG(verifyRemoved(PREInstr));
21882059 PREInstr->deleteValue();
22962167 void GVN::cleanupGlobalSets() {
22972168 VN.clear();
22982169 LeaderTable.clear();
2299 BlockRPONumber.clear();
23002170 TableAllocator.Reset();
23012171 }
23022172
+0
-131
test/Transforms/GVN/PRE/phi-translate-2.ll less more
None ; RUN: opt < %s -gvn -S | FileCheck %s
1 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2
3 @a = common global [100 x i64] zeroinitializer, align 16
4 @b = common global [100 x i64] zeroinitializer, align 16
5 @g1 = common global i64 0, align 8
6 @g2 = common global i64 0, align 8
7 @g3 = common global i64 0, align 8
8 declare i64 @goo(...) local_unnamed_addr #1
9
10 define void @test1(i64 %a, i64 %b, i64 %c, i64 %d) {
11 entry:
12 %mul = mul nsw i64 %b, %a
13 store i64 %mul, i64* @g1, align 8
14 %t0 = load i64, i64* @g2, align 8
15 %cmp = icmp sgt i64 %t0, 3
16 br i1 %cmp, label %if.then, label %if.end
17
18 if.then: ; preds = %entry
19 %mul2 = mul nsw i64 %d, %c
20 store i64 %mul2, i64* @g2, align 8
21 br label %if.end
22
23 ; Check phi-translate works and mul is removed.
24 ; CHECK-LABEL: @test1(
25 ; CHECK: if.end:
26 ; CHECK: %[[MULPHI:.*]] = phi i64 [ {{.*}}, %if.then ], [ %mul, %entry ]
27 ; CHECK-NOT: = mul
28 ; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8
29 if.end: ; preds = %if.then, %entry
30 %b.addr.0 = phi i64 [ %d, %if.then ], [ %b, %entry ]
31 %a.addr.0 = phi i64 [ %c, %if.then ], [ %a, %entry ]
32 %mul3 = mul nsw i64 %a.addr.0, %b.addr.0
33 store i64 %mul3, i64* @g3, align 8
34 ret void
35 }
36
37 define void @test2(i64 %i) {
38 entry:
39 %arrayidx = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i
40 %t0 = load i64, i64* %arrayidx, align 8
41 %arrayidx1 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i
42 %t1 = load i64, i64* %arrayidx1, align 8
43 %mul = mul nsw i64 %t1, %t0
44 store i64 %mul, i64* @g1, align 8
45 %cmp = icmp sgt i64 %mul, 3
46 br i1 %cmp, label %if.then, label %if.end
47
48 ; Check phi-translate works for the phi generated by loadpre. A new mul will be
49 ; inserted in if.then block.
50 ; CHECK-LABEL: @test2(
51 ; CHECK: if.then:
52 ; CHECK: %[[MUL_THEN:.*]] = mul
53 ; CHECK: br label %if.end
54 if.then: ; preds = %entry
55 %call = tail call i64 (...) @goo() #2
56 store i64 %call, i64* @g2, align 8
57 br label %if.end
58
59 ; CHECK: if.end:
60 ; CHECK: %[[MULPHI:.*]] = phi i64 [ %[[MUL_THEN]], %if.then ], [ %mul, %entry ]
61 ; CHECK-NOT: = mul
62 ; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8
63 if.end: ; preds = %if.then, %entry
64 %i.addr.0 = phi i64 [ 3, %if.then ], [ %i, %entry ]
65 %arrayidx3 = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i.addr.0
66 %t2 = load i64, i64* %arrayidx3, align 8
67 %arrayidx4 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i.addr.0
68 %t3 = load i64, i64* %arrayidx4, align 8
69 %mul5 = mul nsw i64 %t3, %t2
70 store i64 %mul5, i64* @g3, align 8
71 ret void
72 }
73
74 ; Check phi-translate doesn't go through backedge, which may lead to incorrect
75 ; pre transformation.
76 ; CHECK: for.end:
77 ; CHECK-NOT: %{{.*pre-phi}} = phi
78 ; CHECK: ret void
79 define void @test3(i64 %N, i64* nocapture readonly %a) {
80 entry:
81 br label %for.cond
82
83 for.cond: ; preds = %for.body, %entry
84 %i.0 = phi i64 [ 0, %entry ], [ %add, %for.body ]
85 %add = add nuw nsw i64 %i.0, 1
86 %arrayidx = getelementptr inbounds i64, i64* %a, i64 %add
87 %tmp0 = load i64, i64* %arrayidx, align 8
88 %cmp = icmp slt i64 %i.0, %N
89 br i1 %cmp, label %for.body, label %for.end
90
91 for.body: ; preds = %for.cond
92 %call = tail call i64 (...) @goo() #2
93 %add1 = sub nsw i64 0, %call
94 %tobool = icmp eq i64 %tmp0, %add1
95 br i1 %tobool, label %for.cond, label %for.end
96
97 for.end: ; preds = %for.body, %for.cond
98 %i.0.lcssa = phi i64 [ %i.0, %for.body ], [ %i.0, %for.cond ]
99 %arrayidx2 = getelementptr inbounds i64, i64* %a, i64 %i.0.lcssa
100 %tmp1 = load i64, i64* %arrayidx2, align 8
101 store i64 %tmp1, i64* @g1, align 8
102 ret void
103 }
104
105 ; It is incorrect to use the value of %andres in last loop iteration
106 ; to do pre.
107 ; CHECK-LABEL: @test4(
108 ; CHECK: for.body:
109 ; CHECK-NOT: %andres.pre-phi = phi i32
110 ; CHECK: br i1 %tobool1
111
112 define i32 @test4(i32 %cond, i32 %SectionAttrs.0231.ph, i32 *%AttrFlag) {
113 for.body.preheader:
114 %t514 = load volatile i32, i32* %AttrFlag
115 br label %for.body
116
117 for.body:
118 %t320 = phi i32 [ %t334, %bb343 ], [ %t514, %for.body.preheader ]
119 %andres = and i32 %t320, %SectionAttrs.0231.ph
120 %tobool1 = icmp eq i32 %andres, 0
121 br i1 %tobool1, label %bb343, label %critedge.loopexit
122
123 bb343:
124 %t334 = load volatile i32, i32* %AttrFlag
125 %tobool2 = icmp eq i32 %cond, 0
126 br i1 %tobool2, label %critedge.loopexit, label %for.body
127
128 critedge.loopexit:
129 unreachable
130 }
3636 %3 = load double, double* %arrayidx5, align 8
3737 ; CHECK: sw.bb2:
3838 ; CHECK-NOT: sext
39 ; CHECK: phi double [
39 ; CHECK-NEXT: phi double [
4040 ; CHECK-NOT: load
4141 %sub6 = fsub double 3.000000e+00, %3
4242 br label %return
7171 %PRE = load i32, i32* %P3
7272 ret i32 %PRE
7373 ; CHECK: block4:
74 ; CHECK: phi i32 [
74 ; CHECK-NEXT: phi i32 [
7575 ; CHECK-NOT: load
7676 ; CHECK: ret i32
7777 }
103103 %PRE = load i32, i32* %P3
104104 ret i32 %PRE
105105 ; CHECK: block4:
106 ; CHECK: phi i32 [
106 ; CHECK-NEXT: phi i32 [
107107 ; CHECK-NOT: load
108108 ; CHECK: ret i32
109109 }
262262 %PRE = load i32, i32* %P3
263263 ret i32 %PRE
264264 ; CHECK: block4:
265 ; CHECK: phi i32 [
265 ; CHECK-NEXT: phi i32 [
266266 ; CHECK-NOT: load
267267 ; CHECK: ret i32
268268 }