Skip to content

Commit 8dbe9af

Browse files
authored
Merge pull request #61671 from nate-chandler/test/20221021/1
[Test] Added arg convenience.
2 parents 9ba404e + 2f18af8 commit 8dbe9af

File tree

5 files changed

+130
-35
lines changed

5 files changed

+130
-35
lines changed

docs/SIL.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3959,6 +3959,10 @@ The following types of test arguments are supported:
39593959
@trace[uint] <-- the ``debug_value [trace]`` at index ``uint``
39603960
@{function}.{trace} <-- the indicated trace in the indicated function
39613961
Example: @function[bar].trace
3962+
- argument: @argument <-_ the first argument of the current block
3963+
@argument[uint] <-- the argument at index ``uint`` of the current block
3964+
@{block}.{argument} <-- the indicated argument in the indicated block
3965+
@{function}.{argument} <-- the indicated argument in the entry block of the indicated function
39623966
- instruction: @instruction <-- the instruction after* the test_specification instruction
39633967
@instruction[+uint] <-- the instruction ``uint`` instructions after* the test_specification instruction
39643968
@instruction[-uint] <-- the instruction ``uint`` instructions before* the test_specification instruction

include/swift/SILOptimizer/Utils/ParseTestSpecification.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_SIL_PARSETESTSPECIFICATION
1919

2020
#include "swift/Basic/TaggedUnion.h"
21+
#include "swift/SIL/SILArgument.h"
2122
#include "swift/SIL/SILInstruction.h"
2223
#include "swift/SIL/SILValue.h"
2324
#include "llvm/ADT/StringRef.h"
@@ -31,6 +32,7 @@ using llvm::StringRef;
3132
namespace swift {
3233

3334
class SILFunction;
35+
class SILArgument;
3436

3537
namespace test {
3638

@@ -42,6 +44,7 @@ struct Argument {
4244
Value,
4345
Operand,
4446
Instruction,
47+
BlockArgument,
4548
Block,
4649
Function,
4750
};
@@ -51,6 +54,7 @@ struct Argument {
5154
SILValue, // ValueArgument
5255
Operand *, // OperandArgument
5356
SILInstruction *, // InstructionArgument
57+
SILArgument *, // BlockArgumentArgument
5458
SILBasicBlock *, // BlockArgument
5559
SILFunction * // FunctionArgument
5660
>;
@@ -89,6 +93,11 @@ struct InstructionArgument
8993
InstructionArgument(SILInstruction *stored) : Super(stored) {}
9094
};
9195

96+
struct BlockArgumentArgument
97+
: ConcreteArgument<SILArgument *, Argument::Kind::BlockArgument> {
98+
BlockArgumentArgument(SILArgument *stored) : Super(stored) {}
99+
};
100+
92101
struct BlockArgument
93102
: ConcreteArgument<SILBasicBlock *, Argument::Kind::Block> {
94103
BlockArgument(SILBasicBlock *stored) : Super(stored) {}
@@ -146,6 +155,9 @@ struct Arguments {
146155
auto *instruction = cast<InstructionArgument>(argument).getValue();
147156
auto *svi = cast<SingleValueInstruction>(instruction);
148157
return svi;
158+
} else if (isa<BlockArgumentArgument>(argument)) {
159+
auto *arg = cast<BlockArgumentArgument>(argument).getValue();
160+
return arg;
149161
}
150162
return cast<ValueArgument>(argument).getValue();
151163
}
@@ -155,6 +167,9 @@ struct Arguments {
155167
SILInstruction *takeInstruction() {
156168
return cast<InstructionArgument>(takeArgument()).getValue();
157169
}
170+
SILArgument *takeBlockArgument() {
171+
return cast<BlockArgumentArgument>(takeArgument()).getValue();
172+
}
158173
SILBasicBlock *takeBlock() {
159174
return cast<BlockArgument>(takeArgument()).getValue();
160175
}

lib/SILOptimizer/UtilityPasses/ParseTestSpecification.cpp

Lines changed: 87 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "swift/SILOptimizer/Utils/ParseTestSpecification.h"
1414
#include "swift/SIL/SILFunction.h"
1515
#include "swift/SIL/SILModule.h"
16+
#include "swift/SIL/SILSuccessor.h"
1617
#include "swift/SILOptimizer/Utils/InstructionDeleter.h"
1718
#include "llvm/ADT/DenseMap.h"
1819
#include "llvm/ADT/SmallVector.h"
@@ -84,55 +85,75 @@ SILInstruction *getInstruction(SILBasicBlock *block, unsigned long index) {
8485
llvm_unreachable("bad index!?");
8586
}
8687

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+
87119
SILInstruction *getInstructionOffsetFrom(SILInstruction *base, long offset) {
88120
if (offset == 0) {
89121
return base;
90122
}
123+
auto *instruction = base;
91124
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!?");
116128
}
129+
return instruction;
117130
}
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;
119137
}
120138

121139
SILBasicBlock *getBlockOffsetFrom(SILBasicBlock *base, long offset) {
122140
if (offset == 0)
123141
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!?");
128147
}
129-
return &*iterator;
148+
return block;
130149
}
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!?");
134155
}
135-
return &*iterator;
156+
return block;
136157
}
137158

138159
SILBasicBlock *getBlock(SILFunction *function, unsigned long index) {
@@ -321,6 +342,31 @@ class ParseArgumentSpecification {
321342
return OperandArgument{operand};
322343
}
323344

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+
324370
using InstructionContext = TaggedUnion<SILFunction *, SILBasicBlock *>;
325371

326372
SILInstruction *
@@ -403,8 +449,10 @@ class ParseArgumentSpecification {
403449
return llvm::None;
404450
if (!consumePrefix("."))
405451
return BlockArgument{block};
406-
if (auto arg = parseInstructionReference({block}))
452+
if (auto arg = parseBlockArgumentReference(block))
407453
return *arg;
454+
if (auto inst = parseInstructionReference({block}))
455+
return *inst;
408456
llvm_unreachable("unhandled suffix after 'block'!?");
409457
}
410458

@@ -444,6 +492,8 @@ class ParseArgumentSpecification {
444492
return llvm::None;
445493
if (!consumePrefix("."))
446494
return FunctionArgument{function};
495+
if (auto arg = parseBlockArgumentReference(function->getEntryBlock()))
496+
return *arg;
447497
if (auto arg = parseInstructionReference({function}))
448498
return *arg;
449499
if (auto arg = parseTraceReference(function))
@@ -461,6 +511,8 @@ class ParseArgumentSpecification {
461511
if (auto arg =
462512
parseOperandReference(getInstruction(context->getFunction(), 0)))
463513
return *arg;
514+
if (auto arg = parseBlockArgumentReference(nullptr))
515+
return *arg;
464516
if (auto arg = parseInstructionReference(llvm::None))
465517
return *arg;
466518
if (auto arg = parseBlockReference(nullptr))

lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class UnitTest {
108108

109109
// Arguments:
110110
// - string: list of characters, each of which specifies subsequent arguments
111+
// - A: (block) argument
111112
// - F: function
112113
// - B: block
113114
// - I: instruction
@@ -129,6 +130,12 @@ struct TestSpecificationTest : UnitTest {
129130
auto expectedFields = arguments.takeString();
130131
for (auto expectedField : expectedFields) {
131132
switch (expectedField) {
133+
case 'A': {
134+
auto *argument = arguments.takeBlockArgument();
135+
llvm::errs() << "argument:\n";
136+
argument->dump();
137+
break;
138+
}
132139
case 'F': {
133140
auto *function = arguments.takeFunction();
134141
llvm::errs() << "function: " << function->getName() << "\n";

test/SILOptimizer/unit_test.sil

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,23 @@ exit:
133133
return %retval : $()
134134
}
135135

136+
struct X {}
137+
138+
// CHECK-LABEL: begin running test 1 of {{[^,]+}} on test_arg_arg_parsing: test-specification-parsing
139+
// CHECK: argument:
140+
// CHECK: %0 = argument of bb0 : $X
141+
// CHECK: argument:
142+
// CHECK: %0 = argument of bb0 : $X
143+
// CHECK: argument:
144+
// CHECK: %0 = argument of bb0 : $X
145+
// CHECK-LABEL: end running test 1 of {{[^,]+}} on test_arg_arg_parsing: test-specification-parsing
146+
sil [ossa] @test_arg_arg_parsing : $(X) -> () {
147+
entry(%instance : $X):
148+
test_specification "test-specification-parsing AAA @argument @block.argument @function.argument[0]"
149+
%retval = tuple ()
150+
return %retval : $()
151+
}
152+
136153
class C {}
137154

138155
sil [ossa] @getC : $@convention(thin) () -> @owned C

0 commit comments

Comments
 (0)