llvm.org GIT mirror llvm / 7838818
IR: Implement uselistorder assembly directives Implement `uselistorder` and `uselistorder_bb` assembly directives, which allow the use-list order to be recovered when round-tripping to assembly. This is the bulk of PR20515. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216025 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
31 changed file(s) with 709 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
17471747 Fast - Allow algebraically equivalent transformations that may
17481748 dramatically change results in floating point (e.g. reassociate). This
17491749 flag implies all the others.
1750
1751 .. _uselistorder:
1752
1753 Use-list Order Directives
1754 -------------------------
1755
1756 Use-list directives encode the in-memory order of each use-list, allowing the
1757 order to be recreated. ```` is a comma-separated list of
1758 indexes that are assigned to the referenced value's uses. The referenced
1759 value's use-list is immediately sorted by these indexes.
1760
1761 Use-list directives may appear at function scope or global scope. They are not
1762 instructions, and have no effect on the semantics of the IR. When they're at
1763 function scope, they must appear after the terminator of the final basic block.
1764
1765 If basic blocks have their address taken via ``blockaddress()`` expressions,
1766 ``uselistorder_bb`` can be used to reorder their use-lists from outside their
1767 function's scope.
1768
1769 :Syntax:
1770
1771 ::
1772
1773 uselistorder , { }
1774 uselistorder_bb @function, %block { }
1775
1776 :Examples:
1777
1778 ::
1779
1780 ; At function scope.
1781 uselistorder i32 %arg1, { 1, 0, 2 }
1782 uselistorder label %bb, { 1, 0 }
1783
1784 ; At global scope.
1785 uselistorder i32* @global, { 1, 2, 0 }
1786 uselistorder i32 7, { 1, 0 }
1787 uselistorder i32 (i32) @bar, { 1, 0 }
1788 uselistorder_bb @foo, %bb, { 5, 1, 3, 2, 0, 4 }
17501789
17511790 .. _typesystem:
17521791
663663 KEYWORD(x);
664664 KEYWORD(blockaddress);
665665
666 // Use-list order directives.
667 KEYWORD(uselistorder);
668 KEYWORD(uselistorder_bb);
669
666670 KEYWORD(personality);
667671 KEYWORD(cleanup);
668672 KEYWORD(catch);
238238 }
239239
240240 case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break;
241 case lltok::kw_uselistorder: if (ParseUseListOrder()) return true; break;
242 case lltok::kw_uselistorder_bb:
243 if (ParseUseListOrderBB()) return true; break;
241244 }
242245 }
243246 }
33703373 }
33713374
33723375 /// ParseFunctionBody
3373 /// ::= '{' BasicBlock+ '}'
3374 ///
3376 /// ::= '{' BasicBlock+ UseListOrderDirective* '}'
33753377 bool LLParser::ParseFunctionBody(Function &Fn) {
33763378 if (Lex.getKind() != lltok::lbrace)
33773379 return TokError("expected '{' in function body");
33893391 SaveAndRestore ScopeExit(BlockAddressPFS, &PFS);
33903392
33913393 // We need at least one basic block.
3392 if (Lex.getKind() == lltok::rbrace)
3394 if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::kw_uselistorder)
33933395 return TokError("function body requires at least one basic block");
33943396
3397 while (Lex.getKind() != lltok::rbrace &&
3398 Lex.getKind() != lltok::kw_uselistorder)
3399 if (ParseBasicBlock(PFS)) return true;
3400
33953401 while (Lex.getKind() != lltok::rbrace)
3396 if (ParseBasicBlock(PFS)) return true;
3402 if (ParseUseListOrder(&PFS))
3403 return true;
33973404
33983405 // Eat the }.
33993406 Lex.Lex();
46534660
46544661 return false;
46554662 }
4663
4664 //===----------------------------------------------------------------------===//
4665 // Use-list order directives.
4666 //===----------------------------------------------------------------------===//
4667 bool LLParser::sortUseListOrder(Value *V, ArrayRef Indexes,
4668 SMLoc Loc) {
4669 if (V->use_empty())
4670 return Error(Loc, "value has no uses");
4671
4672 unsigned NumUses = 0;
4673 SmallDenseMap Order;
4674 for (const Use &U : V->uses()) {
4675 if (++NumUses > Indexes.size())
4676 break;
4677 Order[&U] = Indexes[NumUses - 1];
4678 }
4679 if (NumUses < 2)
4680 return Error(Loc, "value only has one use");
4681 if (Order.size() != Indexes.size() || NumUses > Indexes.size())
4682 return Error(Loc, "wrong number of indexes, expected " +
4683 Twine(std::distance(V->use_begin(), V->use_end())));
4684
4685 V->sortUseList([&](const Use &L, const Use &R) {
4686 return Order.lookup(&L) < Order.lookup(&R);
4687 });
4688 return false;
4689 }
4690
4691 /// ParseUseListOrderIndexes
4692 /// ::= '{' uint32 (',' uint32)+ '}'
4693 bool LLParser::ParseUseListOrderIndexes(SmallVectorImpl &Indexes) {
4694 SMLoc Loc = Lex.getLoc();
4695 if (ParseToken(lltok::lbrace, "expected '{' here"))
4696 return true;
4697 if (Lex.getKind() == lltok::rbrace)
4698 return Lex.Error("expected non-empty list of uselistorder indexes");
4699
4700 // Use Offset, Max, and IsOrdered to check consistency of indexes. The
4701 // indexes should be distinct numbers in the range [0, size-1], and should
4702 // not be in order.
4703 unsigned Offset = 0;
4704 unsigned Max = 0;
4705 bool IsOrdered = true;
4706 assert(Indexes.empty() && "Expected empty order vector");
4707 do {
4708 unsigned Index;
4709 if (ParseUInt32(Index))
4710 return true;
4711
4712 // Update consistency checks.
4713 Offset += Index - Indexes.size();
4714 Max = std::max(Max, Index);
4715 IsOrdered &= Index == Indexes.size();
4716
4717 Indexes.push_back(Index);
4718 } while (EatIfPresent(lltok::comma));
4719
4720 if (ParseToken(lltok::rbrace, "expected '}' here"))
4721 return true;
4722
4723 if (Indexes.size() < 2)
4724 return Error(Loc, "expected >= 2 uselistorder indexes");
4725 if (Offset != 0 || Max >= Indexes.size())
4726 return Error(Loc, "expected distinct uselistorder indexes in range [0, size)");
4727 if (IsOrdered)
4728 return Error(Loc, "expected uselistorder indexes to change the order");
4729
4730 return false;
4731 }
4732
4733 /// ParseUseListOrder
4734 /// ::= 'uselistorder' Type Value ',' UseListOrderIndexes
4735 bool LLParser::ParseUseListOrder(PerFunctionState *PFS) {
4736 SMLoc Loc = Lex.getLoc();
4737 if (ParseToken(lltok::kw_uselistorder, "expected uselistorder directive"))
4738 return true;
4739
4740 Value *V;
4741 SmallVector Indexes;
4742 if (ParseTypeAndValue(V, PFS) ||
4743 ParseToken(lltok::comma, "expected comma in uselistorder directive") ||
4744 ParseUseListOrderIndexes(Indexes))
4745 return true;
4746
4747 return sortUseListOrder(V, Indexes, Loc);
4748 }
4749
4750 /// ParseUseListOrderBB
4751 /// ::= 'uselistorder_bb' @foo ',' %bar ',' UseListOrderIndexes
4752 bool LLParser::ParseUseListOrderBB() {
4753 assert(Lex.getKind() == lltok::kw_uselistorder_bb);
4754 SMLoc Loc = Lex.getLoc();
4755 Lex.Lex();
4756
4757 ValID Fn, Label;
4758 SmallVector Indexes;
4759 if (ParseValID(Fn) ||
4760 ParseToken(lltok::comma, "expected comma in uselistorder_bb directive") ||
4761 ParseValID(Label) ||
4762 ParseToken(lltok::comma, "expected comma in uselistorder_bb directive") ||
4763 ParseUseListOrderIndexes(Indexes))
4764 return true;
4765
4766 // Check the function.
4767 GlobalValue *GV;
4768 if (Fn.Kind == ValID::t_GlobalName)
4769 GV = M->getNamedValue(Fn.StrVal);
4770 else if (Fn.Kind == ValID::t_GlobalID)
4771 GV = Fn.UIntVal < NumberedVals.size() ? NumberedVals[Fn.UIntVal] : nullptr;
4772 else
4773 return Error(Fn.Loc, "expected function name in uselistorder_bb");
4774 if (!GV)
4775 return Error(Fn.Loc, "invalid function forward reference in uselistorder_bb");
4776 auto *F = dyn_cast(GV);
4777 if (!F)
4778 return Error(Fn.Loc, "expected function name in uselistorder_bb");
4779 if (F->isDeclaration())
4780 return Error(Fn.Loc, "invalid declaration in uselistorder_bb");
4781
4782 // Check the basic block.
4783 if (Label.Kind == ValID::t_LocalID)
4784 return Error(Label.Loc, "invalid numeric label in uselistorder_bb");
4785 if (Label.Kind != ValID::t_LocalName)
4786 return Error(Label.Loc, "expected basic block name in uselistorder_bb");
4787 Value *V = F->getValueSymbolTable().lookup(Label.StrVal);
4788 if (!V)
4789 return Error(Label.Loc, "invalid basic block in uselistorder_bb");
4790 if (!isa(V))
4791 return Error(Label.Loc, "expected basic block in uselistorder_bb");
4792
4793 return sortUseListOrder(V, Indexes, Loc);
4794 }
437437 int ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS);
438438 int ParseExtractValue(Instruction *&I, PerFunctionState &PFS);
439439 int ParseInsertValue(Instruction *&I, PerFunctionState &PFS);
440
441 // Use-list order directives.
442 bool ParseUseListOrder(PerFunctionState *PFS = nullptr);
443 bool ParseUseListOrderBB();
444 bool ParseUseListOrderIndexes(SmallVectorImpl &Indexes);
445 bool sortUseListOrder(Value *V, ArrayRef Indexes, SMLoc Loc);
440446 };
441447 } // End llvm namespace
442448
179179 kw_extractelement, kw_insertelement, kw_shufflevector,
180180 kw_extractvalue, kw_insertvalue, kw_blockaddress,
181181
182 // Use-list order directives.
183 kw_uselistorder, kw_uselistorder_bb,
184
182185 // Unsigned Valued tokens (UIntVal).
183186 GlobalID, // @42
184187 LocalVarID, // %42
4848 // Helper Functions
4949 //===----------------------------------------------------------------------===//
5050
51 namespace {
52 struct OrderMap {
53 DenseMap> IDs;
54
55 unsigned size() const { return IDs.size(); }
56 std::pair &operator[](const Value *V) { return IDs[V]; }
57 std::pair lookup(const Value *V) const {
58 return IDs.lookup(V);
59 }
60 void index(const Value *V) {
61 // Explicitly sequence get-size and insert-value operations to avoid UB.
62 unsigned ID = IDs.size() + 1;
63 IDs[V].first = ID;
64 }
65 };
66 }
67
68 static void orderValue(const Value *V, OrderMap &OM) {
69 if (OM.lookup(V).first)
70 return;
71
72 if (const Constant *C = dyn_cast(V))
73 if (C->getNumOperands() && !isa(C))
74 for (const Value *Op : C->operands())
75 if (!isa(Op) && !isa(Op))
76 orderValue(Op, OM);
77
78 // Note: we cannot cache this lookup above, since inserting into the map
79 // changes the map's size, and thus affects the other IDs.
80 OM.index(V);
81 }
82
83 static OrderMap orderModule(const Module *M) {
84 // This needs to match the order used by ValueEnumerator::ValueEnumerator()
85 // and ValueEnumerator::incorporateFunction().
86 OrderMap OM;
87
88 for (const GlobalVariable &G : M->globals()) {
89 if (G.hasInitializer())
90 if (!isa(G.getInitializer()))
91 orderValue(G.getInitializer(), OM);
92 orderValue(&G, OM);
93 }
94 for (const GlobalAlias &A : M->aliases()) {
95 if (!isa(A.getAliasee()))
96 orderValue(A.getAliasee(), OM);
97 orderValue(&A, OM);
98 }
99 for (const Function &F : *M) {
100 if (F.hasPrefixData())
101 if (!isa(F.getPrefixData()))
102 orderValue(F.getPrefixData(), OM);
103 orderValue(&F, OM);
104
105 if (F.isDeclaration())
106 continue;
107
108 for (const Argument &A : F.args())
109 orderValue(&A, OM);
110 for (const BasicBlock &BB : F) {
111 orderValue(&BB, OM);
112 for (const Instruction &I : BB) {
113 for (const Value *Op : I.operands())
114 if ((isa(*Op) && !isa(*Op)) ||
115 isa(*Op))
116 orderValue(Op, OM);
117 orderValue(&I, OM);
118 }
119 }
120 }
121 return OM;
122 }
123
124 static void predictValueUseListOrderImpl(const Value *V, const Function *F,
125 unsigned ID, const OrderMap &OM,
126 UseListOrderStack &Stack) {
127 // Predict use-list order for this one.
128 typedef std::pair Entry;
129 SmallVector List;
130 for (const Use &U : V->uses())
131 // Check if this user will be serialized.
132 if (OM.lookup(U.getUser()).first)
133 List.push_back(std::make_pair(&U, List.size()));
134
135 if (List.size() < 2)
136 // We may have lost some users.
137 return;
138
139 bool GetsReversed =
140 !isa(V) && !isa(V) && !isa(V);
141 if (auto *BA = dyn_cast(V))
142 ID = OM.lookup(BA->getBasicBlock()).first;
143 std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
144 const Use *LU = L.first;
145 const Use *RU = R.first;
146 if (LU == RU)
147 return false;
148
149 auto LID = OM.lookup(LU->getUser()).first;
150 auto RID = OM.lookup(RU->getUser()).first;
151
152 // If ID is 4, then expect: 7 6 5 1 2 3.
153 if (LID < RID) {
154 if (GetsReversed)
155 if (RID <= ID)
156 return true;
157 return false;
158 }
159 if (RID < LID) {
160 if (GetsReversed)
161 if (LID <= ID)
162 return false;
163 return true;
164 }
165
166 // LID and RID are equal, so we have different operands of the same user.
167 // Assume operands are added in order for all instructions.
168 if (GetsReversed)
169 if (LID <= ID)
170 return LU->getOperandNo() < RU->getOperandNo();
171 return LU->getOperandNo() > RU->getOperandNo();
172 });
173
174 if (std::is_sorted(
175 List.begin(), List.end(),
176 [](const Entry &L, const Entry &R) { return L.second < R.second; }))
177 // Order is already correct.
178 return;
179
180 // Store the shuffle.
181 Stack.emplace_back(V, F, List.size());
182 assert(List.size() == Stack.back().Shuffle.size() && "Wrong size");
183 for (size_t I = 0, E = List.size(); I != E; ++I)
184 Stack.back().Shuffle[I] = List[I].second;
185 }
186
187 static void predictValueUseListOrder(const Value *V, const Function *F,
188 OrderMap &OM, UseListOrderStack &Stack) {
189 auto &IDPair = OM[V];
190 assert(IDPair.first && "Unmapped value");
191 if (IDPair.second)
192 // Already predicted.
193 return;
194
195 // Do the actual prediction.
196 IDPair.second = true;
197 if (!V->use_empty() && std::next(V->use_begin()) != V->use_end())
198 predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack);
199
200 // Recursive descent into constants.
201 if (const Constant *C = dyn_cast(V))
202 if (C->getNumOperands()) // Visit GlobalValues.
203 for (const Value *Op : C->operands())
204 if (isa(Op)) // Visit GlobalValues.
205 predictValueUseListOrder(Op, F, OM, Stack);
206 }
207
208 static UseListOrderStack predictUseListOrder(const Module *M) {
209 OrderMap OM = orderModule(M);
210
211 // Use-list orders need to be serialized after all the users have been added
212 // to a value, or else the shuffles will be incomplete. Store them per
213 // function in a stack.
214 //
215 // Aside from function order, the order of values doesn't matter much here.
216 UseListOrderStack Stack;
217
218 // We want to visit the functions backward now so we can list function-local
219 // constants in the last Function they're used in. Module-level constants
220 // have already been visited above.
221 for (auto I = M->rbegin(), E = M->rend(); I != E; ++I) {
222 const Function &F = *I;
223 if (F.isDeclaration())
224 continue;
225 for (const BasicBlock &BB : F)
226 predictValueUseListOrder(&BB, &F, OM, Stack);
227 for (const Argument &A : F.args())
228 predictValueUseListOrder(&A, &F, OM, Stack);
229 for (const BasicBlock &BB : F)
230 for (const Instruction &I : BB)
231 for (const Value *Op : I.operands())
232 if (isa(*Op) || isa(*Op)) // Visit GlobalValues.
233 predictValueUseListOrder(Op, &F, OM, Stack);
234 for (const BasicBlock &BB : F)
235 for (const Instruction &I : BB)
236 predictValueUseListOrder(&I, &F, OM, Stack);
237 }
238
239 // Visit globals last.
240 for (const GlobalVariable &G : M->globals())
241 predictValueUseListOrder(&G, nullptr, OM, Stack);
242 for (const Function &F : *M)
243 predictValueUseListOrder(&F, nullptr, OM, Stack);
244 for (const GlobalAlias &A : M->aliases())
245 predictValueUseListOrder(&A, nullptr, OM, Stack);
246 for (const GlobalVariable &G : M->globals())
247 if (G.hasInitializer())
248 predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
249 for (const GlobalAlias &A : M->aliases())
250 predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
251 for (const Function &F : *M)
252 if (F.hasPrefixData())
253 predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack);
254
255 return Stack;
256 }
257
51258 static const Module *getModuleFromVal(const Value *V) {
52259 if (const Argument *MA = dyn_cast(V))
53260 return MA->getParent() ? MA->getParent()->getParent() : nullptr;
345552 TheFunction = F;
346553 FunctionProcessed = false;
347554 }
555
556 const Function *getFunction() const { return TheFunction; }
348557
349558 /// After calling incorporateFunction, use this method to remove the
350559 /// most recently incorporated function from the SlotTracker. This
12781487 void AssemblyWriter::printModule(const Module *M) {
12791488 Machine.initialize();
12801489
1490 if (shouldPreserveAssemblyUseListOrder())
1491 UseListOrders = predictUseListOrder(M);
1492
12811493 if (!M->getModuleIdentifier().empty() &&
12821494 // Don't print the ID if it will start a new line (which would
12831495 // require a comment char before it).
13381550 I != E; ++I)
13391551 printAlias(I);
13401552
1553 // Output global use-lists.
1554 printUseLists(nullptr);
1555
13411556 // Output all of the functions.
13421557 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
13431558 printFunction(I);
1559 assert(UseListOrders.empty() && "All use-lists should have been consumed");
13441560
13451561 // Output all attribute groups.
13461562 if (!Machine.as_empty()) {
16911907 for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I)
16921908 printBasicBlock(I);
16931909
1910 // Output the function's use-lists.
1911 printUseLists(F);
1912
16941913 Out << "}\n";
16951914 }
16961915
21672386 }
21682387
21692388 } // namespace llvm
2389
2390 void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {
2391 bool IsInFunction = Machine.getFunction();
2392 if (IsInFunction)
2393 Out << " ";
2394
2395 Out << "uselistorder";
2396 if (const BasicBlock *BB =
2397 IsInFunction ? nullptr : dyn_cast(Order.V)) {
2398 Out << "_bb ";
2399 writeOperand(BB->getParent(), false);
2400 Out << ", ";
2401 writeOperand(BB, false);
2402 } else {
2403 Out << " ";
2404 writeOperand(Order.V, true);
2405 }
2406 Out << ", { ";
2407
2408 assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
2409 Out << Order.Shuffle[0];
2410 for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I)
2411 Out << ", " << Order.Shuffle[I];
2412 Out << " }\n";
2413 }
2414
2415 void AssemblyWriter::printUseLists(const Function *F) {
2416 auto hasMore =
2417 [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; };
2418 if (!hasMore())
2419 // Nothing to do.
2420 return;
2421
2422 Out << "\n; uselistorder directives\n";
2423 while (hasMore()) {
2424 printUseListOrder(UseListOrders.back());
2425 UseListOrders.pop_back();
2426 }
2427 }
21702428
21712429 //===----------------------------------------------------------------------===//
21722430 // External Interface declarations
1919 #include "llvm/IR/Attributes.h"
2020 #include "llvm/IR/Instructions.h"
2121 #include "llvm/IR/TypeFinder.h"
22 #include "llvm/IR/UseListOrder.h"
2223 #include "llvm/Support/FormattedStream.h"
2324
2425 namespace llvm {
7273 TypePrinting TypePrinter;
7374 AssemblyAnnotationWriter *AnnotationWriter;
7475 SetVector Comdats;
76 UseListOrderStack UseListOrders;
7577
7678 public:
7779 /// Construct an AssemblyWriter with an external SlotTracker
110112 void printInstructionLine(const Instruction &I);
111113 void printInstruction(const Instruction &I);
112114
115 void printUseListOrder(const UseListOrder &Order);
116 void printUseLists(const Function *F);
117
113118 private:
114119 void init();
115120
0 ; RUN: verify-uselistorder < %s
1
2 ; Globals.
3 @global = global i32 0
4 @alias.ref1 = global i32* getelementptr inbounds (i32* @alias, i64 1)
5 @alias.ref2 = global i32* getelementptr inbounds (i32* @alias, i64 1)
6
7 ; Aliases.
8 @alias = alias i32* @global
9 @alias.ref3 = alias i32* getelementptr inbounds (i32* @alias, i64 1)
10 @alias.ref4 = alias i32* getelementptr inbounds (i32* @alias, i64 1)
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: expected uselistorder directive
2
3 define i32 @f32(i32 %a, i32 %b, i32 %c, i32 %d) {
4 entry:
5 br label %first
6
7 ;
8 %eh = mul i32 %e, %1
9 %sum = add i32 %eh, %ef
10 br label %preexit
11
12 preexit:
13 %product = phi i32 [%ef, %first], [%sum, %0]
14 %backto0 = icmp slt i32 %product, -9
15 br i1 %backto0, label %0, label %exit
16
17 first:
18 %e = add i32 %a, 7
19 %f = add i32 %b, 7
20 %g = add i32 %c, 8
21 %1 = add i32 %d, 8
22 %ef = mul i32 %e, %f
23 %g1 = mul i32 %g, %1
24 %goto0 = icmp slt i32 %g1, -9
25 br i1 %goto0, label %0, label %preexit
26
27 ; uselistorder directives
28 uselistorder i32 7, { 1, 0 }
29 uselistorder i32 %1, { 1, 0 }
30 uselistorder i32 %e, { 1, 0 }
31 uselistorder label %0, { 1, 0 }
32 uselistorder label %preexit, { 1, 0 }
33
34 exit:
35 ret i32 %product
36 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: value has no uses
2 define void @foo() {
3 unreachable
4 uselistorder i32 %val, { 1, 0 }
5 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: value has no uses
2 define void @foo() {
3 unreachable
4 uselistorder i32 %1, { 1, 0 }
5 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: value has no uses
2 uselistorder i32* @global, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: expected distinct uselistorder indexes in range [0, size)
2 @global = global i32 0
3 @alias1 = alias i32* @global
4 @alias2 = alias i32* @global
5 @alias3 = alias i32* @global
6 uselistorder i32* @global, { 0, 0, 2 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: value has no uses
2 @global = global i32 0
3 uselistorder i32* @global, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: value only has one use
2 @global = global i32 0
3 @alias = alias i32* @global
4 uselistorder i32* @global, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: expected uselistorder indexes to change the order
2 @global = global i32 0
3 @alias1 = alias i32* @global
4 @alias2 = alias i32* @global
5 @alias3 = alias i32* @global
6 uselistorder i32* @global, { 0, 1, 2 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: expected distinct uselistorder indexes in range [0, size)
2 @global = global i32 0
3 @alias1 = alias i32* @global
4 @alias2 = alias i32* @global
5 @alias3 = alias i32* @global
6 uselistorder i32* @global, { 0, 3, 1 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: wrong number of indexes, expected 3
2 @global = global i32 0
3 @alias1 = alias i32* @global
4 @alias2 = alias i32* @global
5 @alias3 = alias i32* @global
6 uselistorder i32* @global, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: wrong number of indexes, expected 2
2 @global = global i32 0
3 @alias1 = alias i32* @global
4 @alias2 = alias i32* @global
5 uselistorder i32* @global, { 1, 0, 2 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: '@global' defined with type 'i32*'
2 @global = global i32 0
3 uselistorder i31* @global, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: invalid basic block in uselistorder_bb
2 define void @foo() {
3 unreachable
4 }
5 uselistorder_bb @foo, %bb, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: invalid declaration in uselistorder_bb
2 declare void @foo()
3 uselistorder_bb @foo, %bb, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: invalid function forward reference in uselistorder_bb
2 uselistorder_bb @foo, %bb, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: expected basic block in uselistorder_bb
2 define i32 @foo(i32 %arg) {
3 ret i32 %arg
4 }
5 uselistorder_bb @foo, %arg, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: expected function name in uselistorder_bb
2 @global = global i1 0
3 uselistorder_bb @global, %bb, { 1, 0 }
0 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
1 ; CHECK: error: invalid numeric label in uselistorder_bb
2
3 @ba1 = constant i8* blockaddress (@foo, %1)
4
5 define void @foo() {
6 br label %1
7 unreachable
8 }
9
10 uselistorder_bb @foo, %1, { 1, 0 }
0 ; RUN: llvm-as < %s -disable-output 2>&1 | FileCheck %s -allow-empty
1 ; CHECK-NOT: error
2 ; CHECK-NOT: warning
3 ; RUN: verify-uselistorder < %s
4
5 @a = global [4 x i1] [i1 0, i1 1, i1 0, i1 1]
6 @b = alias i1* getelementptr ([4 x i1]* @a, i64 0, i64 2)
7
8 ; Check use-list order of constants used by globals.
9 @glob1 = global i5 7
10 @glob2 = global i5 7
11 @glob3 = global i5 7
12
13 define i32 @f32(i32 %a, i32 %b, i32 %c, i32 %d) {
14 entry:
15 br label %first
16
17 ;
18 %eh = mul i32 %e, %1
19 %sum = add i32 %eh, %ef
20 br label %preexit
21
22 preexit:
23 %product = phi i32 [%ef, %first], [%sum, %0]
24 %backto0 = icmp slt i32 %product, -9
25 br i1 %backto0, label %0, label %exit
26
27 exit:
28 ret i32 %product
29
30 first:
31 %e = add i32 %a, 7
32 %f = add i32 %b, 7
33 %g = add i32 %c, 8
34 %1 = add i32 %d, 8
35 %ef = mul i32 %e, %f
36 %g1 = mul i32 %g, %1
37 %goto0 = icmp slt i32 %g1, -9
38 br i1 %goto0, label %0, label %preexit
39
40 ; uselistorder directives
41 uselistorder i32 7, { 1, 0 }
42 uselistorder i32 %1, { 1, 0 }
43 uselistorder i32 %e, { 1, 0 }
44 uselistorder label %0, { 1, 0 }
45 uselistorder label %preexit, { 1, 0 }
46 }
47
48 define i1 @loada() {
49 entry:
50 %a = load i1* getelementptr ([4 x i1]* @a, i64 0, i64 2)
51 ret i1 %a
52 }
53
54 uselistorder i5 7, { 1, 0, 2 }
55 uselistorder i1* getelementptr ([4 x i1]* @a, i64 0, i64 2), { 1, 0 }
0 ; RUN: llvm-as < %s -disable-output 2>&1 | FileCheck %s -allow-empty
1 ; CHECK-NOT: error
2 ; CHECK-NOT: warning
3 ; RUN: verify-uselistorder < %s
4
5 @ba1 = constant i8* blockaddress (@bafunc1, %bb)
6 @ba2 = constant i8* getelementptr (i8* blockaddress (@bafunc2, %bb), i61 0)
7 @ba3 = constant i8* getelementptr (i8* blockaddress (@bafunc2, %bb), i61 0)
8
9 define i8* @babefore() {
10 ret i8* getelementptr (i8* blockaddress (@bafunc2, %bb), i61 0)
11 bb1:
12 ret i8* blockaddress (@bafunc1, %bb)
13 bb2:
14 ret i8* blockaddress (@bafunc3, %bb)
15 }
16 define void @bafunc1() {
17 br label %bb
18 bb:
19 unreachable
20 }
21 define void @bafunc2() {
22 br label %bb
23 bb:
24 unreachable
25 }
26 define void @bafunc3() {
27 br label %bb
28 bb:
29 unreachable
30 }
31 define i8* @baafter() {
32 ret i8* blockaddress (@bafunc2, %bb)
33 bb1:
34 ret i8* blockaddress (@bafunc1, %bb)
35 bb2:
36 ret i8* blockaddress (@bafunc3, %bb)
37 }
38
39 uselistorder_bb @bafunc1, %bb, { 1, 0 }
40 uselistorder_bb @bafunc2, %bb, { 1, 0 }
41 uselistorder_bb @bafunc3, %bb, { 1, 0 }
364364
365365 static void verifyUseListOrder(const Module &M) {
366366 verifyBitcodeUseListOrder(M);
367 if (shouldPreserveAssemblyUseListOrder())
368 verifyAssemblyUseListOrder(M);
367 verifyAssemblyUseListOrder(M);
369368 }
370369
371370 static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen,
531530 report_fatal_error("verification failed");
532531
533532 errs() << "*** verify-use-list-order ***\n";
533 // Can't verify if order isn't preserved.
534534 if (!shouldPreserveBitcodeUseListOrder()) {
535 // Can't verify if order isn't preserved.
536535 errs() << "warning: forcing -preserve-bc-use-list-order\n";
537536 setPreserveBitcodeUseListOrder(true);
537 }
538 if (!shouldPreserveAssemblyUseListOrder()) {
539 errs() << "warning: forcing -preserve-ll-use-list-order\n";
540 setPreserveAssemblyUseListOrder(true);
538541 }
539542
540543 // Verify the use lists now and after reversing them.
4747 `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face)
4848 ;; Aggregate ops
4949 `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face)
50 ;; Use-list order directives
51 `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face)
5052
5153 )
5254 "Syntax highlighting for LLVM"
5656 syn keyword llvmKeyword unordered uwtable volatile weak weak_odr
5757 syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc x86_64_sysvcc
5858 syn keyword llvmKeyword x86_64_win64cc zeroext
59 syn keyword llvmKeyword uselistorder uselistorder_bb
5960
6061 " Obsolete keywords.
6162 syn keyword llvmError getresult begin end