13
13
#include " swift/SILOptimizer/Utils/ParseTestSpecification.h"
14
14
#include " swift/SIL/SILFunction.h"
15
15
#include " swift/SIL/SILModule.h"
16
+ #include " swift/SIL/SILSuccessor.h"
16
17
#include " swift/SILOptimizer/Utils/InstructionDeleter.h"
17
18
#include " llvm/ADT/DenseMap.h"
18
19
#include " llvm/ADT/SmallVector.h"
@@ -84,55 +85,75 @@ SILInstruction *getInstruction(SILBasicBlock *block, unsigned long index) {
84
85
llvm_unreachable (" bad index!?" );
85
86
}
86
87
88
+ SILBasicBlock *getNextBlock (SILBasicBlock *block) {
89
+ auto next = std::next (block->getIterator ());
90
+ if (next == block->getFunction ()->end ())
91
+ return nullptr ;
92
+ return &*next;
93
+ }
94
+
95
+ SILBasicBlock *getPreviousBlock (SILBasicBlock *block) {
96
+ auto iterator = block->getIterator ();
97
+ if (iterator == block->getFunction ()->begin ())
98
+ return nullptr ;
99
+ return &*std::prev (iterator);
100
+ }
101
+
102
+ SILInstruction *getNextInstructionIgnoringBlocks (SILInstruction *instruction) {
103
+ if (auto *nextInstruction = instruction->getNextInstruction ())
104
+ return nextInstruction;
105
+ if (auto *nextBlock = getNextBlock (instruction->getParent ()))
106
+ return &nextBlock->front ();
107
+ return nullptr ;
108
+ }
109
+
110
+ SILInstruction *
111
+ getPreviousInstructionIgnoringBlocks (SILInstruction *instruction) {
112
+ if (auto *previousInstruction = instruction->getPreviousInstruction ())
113
+ return previousInstruction;
114
+ if (auto *previousBlock = getPreviousBlock (instruction->getParent ()))
115
+ return &previousBlock->back ();
116
+ return nullptr ;
117
+ }
118
+
87
119
SILInstruction *getInstructionOffsetFrom (SILInstruction *base, long offset) {
88
120
if (offset == 0 ) {
89
121
return base;
90
122
}
123
+ auto *instruction = base;
91
124
if (offset > 0 ) {
92
- Optional<unsigned long > baseIndex;
93
- unsigned long index = 0 ;
94
- for (auto &block : *base->getFunction ()) {
95
- for (auto &other : block) {
96
- if (baseIndex && index == (*baseIndex + offset)) {
97
- return &other;
98
- }
99
- if (&other == base) {
100
- baseIndex = index;
101
- }
102
- ++index;
103
- }
104
- }
105
- llvm_unreachable (" positive offset outside of function!?" );
106
- }
107
- SmallVector<SILInstruction *, 64 > instructions;
108
- unsigned long index = 0 ;
109
- for (auto &block : *base->getFunction ()) {
110
- for (auto &other : block) {
111
- instructions.push_back (&other);
112
- if (&other == base) {
113
- return instructions[index + offset];
114
- }
115
- ++index;
125
+ for (auto index = 0 ; index < offset; ++index) {
126
+ instruction = getNextInstructionIgnoringBlocks (instruction);
127
+ assert (instruction && " too large an offset!?" );
116
128
}
129
+ return instruction;
117
130
}
118
- llvm_unreachable (" never found instruction in its own function!?" );
131
+ // offset < 0
132
+ for (auto index = 0 ; index > offset; --index) {
133
+ instruction = getPreviousInstructionIgnoringBlocks (instruction);
134
+ assert (instruction && " too negative an offset!?" );
135
+ }
136
+ return instruction;
119
137
}
120
138
121
139
SILBasicBlock *getBlockOffsetFrom (SILBasicBlock *base, long offset) {
122
140
if (offset == 0 )
123
141
return base;
124
- if (offset < 0 ) {
125
- auto iterator = base->getIterator ();
126
- for (auto counter = 0 ; counter > offset; --counter) {
127
- iterator = std::prev (iterator);
142
+ if (offset > 0 ) {
143
+ auto *block = base;
144
+ for (auto counter = 0 ; counter < offset; ++counter) {
145
+ block = getNextBlock (block);
146
+ assert (block && " too large an offset!?" );
128
147
}
129
- return &*iterator ;
148
+ return block ;
130
149
}
131
- auto iterator = base->getIterator ();
132
- for (auto counter = 0 ; counter < offset; ++counter) {
133
- iterator = std::next (iterator);
150
+ // offset < 0
151
+ auto *block = base;
152
+ for (auto counter = 0 ; counter > offset; --counter) {
153
+ block = getPreviousBlock (block);
154
+ assert (block && " too negative an offset!?" );
134
155
}
135
- return &*iterator ;
156
+ return block ;
136
157
}
137
158
138
159
SILBasicBlock *getBlock (SILFunction *function, unsigned long index) {
@@ -321,6 +342,31 @@ class ParseArgumentSpecification {
321
342
return OperandArgument{operand};
322
343
}
323
344
345
+ SILArgument *parseBlockArgumentComponent (SILBasicBlock *block) {
346
+ if (!consumePrefix (" argument" ))
347
+ return nullptr ;
348
+ // If this is a bare @argument reference, it refers to the first argument
349
+ // of the block containing the test_specification.
350
+ if (!block) {
351
+ block = context->getParent ();
352
+ }
353
+ if (empty ()) {
354
+ return block->getArgument (0 );
355
+ }
356
+ if (auto subscript = parseSubscript ()) {
357
+ auto index = subscript->get <unsigned long long >();
358
+ return block->getArgument (index);
359
+ }
360
+ llvm_unreachable (" bad suffix after 'argument'!?" );
361
+ }
362
+
363
+ Optional<Argument> parseBlockArgumentReference (SILBasicBlock *block) {
364
+ auto *argument = parseBlockArgumentComponent (block);
365
+ if (!argument)
366
+ return llvm::None;
367
+ return BlockArgumentArgument{argument};
368
+ }
369
+
324
370
using InstructionContext = TaggedUnion<SILFunction *, SILBasicBlock *>;
325
371
326
372
SILInstruction *
@@ -403,8 +449,10 @@ class ParseArgumentSpecification {
403
449
return llvm::None;
404
450
if (!consumePrefix (" ." ))
405
451
return BlockArgument{block};
406
- if (auto arg = parseInstructionReference ({ block} ))
452
+ if (auto arg = parseBlockArgumentReference ( block))
407
453
return *arg;
454
+ if (auto inst = parseInstructionReference ({block}))
455
+ return *inst;
408
456
llvm_unreachable (" unhandled suffix after 'block'!?" );
409
457
}
410
458
@@ -444,6 +492,8 @@ class ParseArgumentSpecification {
444
492
return llvm::None;
445
493
if (!consumePrefix (" ." ))
446
494
return FunctionArgument{function};
495
+ if (auto arg = parseBlockArgumentReference (function->getEntryBlock ()))
496
+ return *arg;
447
497
if (auto arg = parseInstructionReference ({function}))
448
498
return *arg;
449
499
if (auto arg = parseTraceReference (function))
@@ -461,6 +511,8 @@ class ParseArgumentSpecification {
461
511
if (auto arg =
462
512
parseOperandReference (getInstruction (context->getFunction (), 0 )))
463
513
return *arg;
514
+ if (auto arg = parseBlockArgumentReference (nullptr ))
515
+ return *arg;
464
516
if (auto arg = parseInstructionReference (llvm::None))
465
517
return *arg;
466
518
if (auto arg = parseBlockReference (nullptr ))
0 commit comments