Skip to content

Commit f8e2925

Browse files
authored
Merge pull request #5358 from gottesmm/irgen_gardening
2 parents e3c3cc5 + f1734ec commit f8e2925

File tree

4 files changed

+217
-192
lines changed

4 files changed

+217
-192
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 5 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,17 @@
113113
#include "llvm/Analysis/CFG.h"
114114
#include "clang/CodeGen/SwiftCallingConv.h"
115115

116-
#include "IRGenModule.h"
117-
#include "LoadableTypeInfo.h"
118-
#include "NonFixedTypeInfo.h"
119-
#include "ResilientTypeInfo.h"
120116
#include "GenMeta.h"
121117
#include "GenProto.h"
122118
#include "GenType.h"
123119
#include "IRGenDebugInfo.h"
120+
#include "IRGenModule.h"
121+
#include "LoadableTypeInfo.h"
122+
#include "NonFixedTypeInfo.h"
123+
#include "ResilientTypeInfo.h"
124124
#include "ScalarTypeInfo.h"
125125
#include "StructLayout.h"
126+
#include "SwitchBuilder.h"
126127

127128
using namespace swift;
128129
using namespace irgen;
@@ -239,190 +240,6 @@ irgen::EnumImplStrategy::getResilientTagIndex(EnumElementDecl *Case) const {
239240
}
240241

241242
namespace {
242-
/// A builder that produces an LLVM branch or switch instruction for a set
243-
/// of destinations.
244-
class SwitchBuilder {
245-
private:
246-
#ifndef NDEBUG
247-
/// Track whether we added as many cases as we expected to.
248-
unsigned CasesToAdd;
249-
#endif
250-
251-
protected:
252-
IRBuilder Builder;
253-
llvm::Value *Subject;
254-
255-
/// Protected initializer. Clients should use the `create` factory method.
256-
SwitchBuilder(IRGenFunction &IGF, llvm::Value *Subject, unsigned NumCases)
257-
:
258-
#ifndef NDEBUG
259-
CasesToAdd(NumCases),
260-
#endif
261-
// Create our own IRBuilder, so that the SwitchBuilder is always able to
262-
// generate the branch instruction at the right point, even if it needs
263-
// to collect multiple cases before building an instruction.
264-
Builder(IGF.IGM.getLLVMContext(), /*DebugInfo*/ false), Subject(Subject)
265-
{
266-
// Start our builder off at IGF's current insertion point.
267-
Builder.SetInsertPoint(IGF.Builder.GetInsertBlock(),
268-
IGF.Builder.GetInsertPoint());
269-
}
270-
271-
public:
272-
#ifndef NDEBUG
273-
virtual ~SwitchBuilder() {
274-
assert(CasesToAdd == 0 && "Did not add enough cases");
275-
}
276-
#endif
277-
278-
// Create a SwitchBuilder instance for a switch that will have the given
279-
// number of cases.
280-
static std::unique_ptr<SwitchBuilder>
281-
create(IRGenFunction &IGF, llvm::Value *Subject,
282-
SwitchDefaultDest Default,
283-
unsigned NumCases);
284-
285-
/// Add a case to the switch.
286-
virtual void addCase(llvm::ConstantInt *value, llvm::BasicBlock *dest) {
287-
#ifndef NDEBUG
288-
assert(CasesToAdd > 0 && "Added too many cases");
289-
--CasesToAdd;
290-
#endif
291-
}
292-
};
293-
294-
/// A builder that emits an unconditional branch for a "switch" with only
295-
/// one destination.
296-
class BrSwitchBuilder final : public SwitchBuilder {
297-
private:
298-
friend class SwitchBuilder;
299-
300-
BrSwitchBuilder(IRGenFunction &IGF, llvm::Value *Subject, unsigned NumCases)
301-
: SwitchBuilder(IGF, Subject, NumCases)
302-
{
303-
assert(NumCases == 1 && "should have only one branch");
304-
}
305-
306-
public:
307-
void addCase(llvm::ConstantInt *value, llvm::BasicBlock *dest) override {
308-
SwitchBuilder::addCase(value, dest);
309-
Builder.CreateBr(dest);
310-
}
311-
};
312-
313-
/// A builder that produces a conditional branch for a "switch" with two
314-
/// defined destinations.
315-
class CondBrSwitchBuilder final : public SwitchBuilder {
316-
private:
317-
friend class SwitchBuilder;
318-
llvm::BasicBlock *FirstDest;
319-
320-
CondBrSwitchBuilder(IRGenFunction &IGF, llvm::Value *Subject,
321-
SwitchDefaultDest Default,
322-
unsigned NumCases)
323-
: SwitchBuilder(IGF, Subject, NumCases),
324-
FirstDest(Default.getInt() == IsUnreachable
325-
? nullptr : Default.getPointer())
326-
{
327-
assert(NumCases + (Default.getInt() == IsNotUnreachable) == 2
328-
&& "should have two branches total");
329-
}
330-
331-
public:
332-
void addCase(llvm::ConstantInt *value, llvm::BasicBlock *dest) override {
333-
SwitchBuilder::addCase(value, dest);
334-
335-
// If we don't have a first destination yet, save it.
336-
// We don't need to save the value in this case since we assume that the
337-
// subject must be one of the case values. We only have to test one or
338-
// the other.
339-
//
340-
// TODO: It may make sense to save both case values, and pick which one
341-
// to compare based on which value is more likely to be efficiently
342-
// representable in the target machine language. For example, zero
343-
// or a small immediate is usually cheaper to materialize than a larger
344-
// value that may require multiple instructions or a bigger encoding.
345-
if (!FirstDest) {
346-
FirstDest = dest;
347-
return;
348-
}
349-
350-
// Otherwise, we have both destinations for the branch and a value to
351-
// test against. We can make the instruction now.
352-
if (cast<llvm::IntegerType>(Subject->getType())->getBitWidth() == 1) {
353-
// If the subject is already i1, we can use it directly as the branch
354-
// condition.
355-
if (value->isZero())
356-
Builder.CreateCondBr(Subject, FirstDest, dest);
357-
else
358-
Builder.CreateCondBr(Subject, dest, FirstDest);
359-
return;
360-
}
361-
// Otherwise, compare against the case value we have.
362-
auto test = Builder.CreateICmpNE(Subject, value);
363-
Builder.CreateCondBr(test, FirstDest, dest);
364-
}
365-
};
366-
367-
/// A builder that produces a switch instruction for a switch with many
368-
/// destinations.
369-
class SwitchSwitchBuilder final : public SwitchBuilder {
370-
private:
371-
friend class SwitchBuilder;
372-
llvm::SwitchInst *TheSwitch;
373-
374-
SwitchSwitchBuilder(IRGenFunction &IGF, llvm::Value *Subject,
375-
SwitchDefaultDest Default,
376-
unsigned NumCases)
377-
: SwitchBuilder(IGF, Subject, NumCases)
378-
{
379-
TheSwitch = IGF.Builder.CreateSwitch(Subject, Default.getPointer(),
380-
NumCases);
381-
}
382-
383-
public:
384-
void addCase(llvm::ConstantInt *value, llvm::BasicBlock *dest) override {
385-
SwitchBuilder::addCase(value, dest);
386-
TheSwitch->addCase(value, dest);
387-
}
388-
};
389-
390-
std::unique_ptr<SwitchBuilder>
391-
SwitchBuilder::create(IRGenFunction &IGF, llvm::Value *Subject,
392-
SwitchDefaultDest Default, unsigned NumCases) {
393-
// Pick a builder based on how many total reachable destinations we intend
394-
// to have.
395-
switch (NumCases + (Default.getInt() == IsNotUnreachable)) {
396-
case 0:
397-
// No reachable destinations. We can emit an unreachable and go about
398-
// our business.
399-
IGF.Builder.CreateUnreachable();
400-
return nullptr;
401-
case 1:
402-
// One reachable destination. We can emit an unconditional branch.
403-
// If that one branch is the default, we're done.
404-
if (Default.getInt() == IsNotUnreachable) {
405-
IGF.Builder.CreateBr(Default.getPointer());
406-
return nullptr;
407-
}
408-
409-
// Otherwise, use a builder to emit the one case.
410-
return std::unique_ptr<SwitchBuilder>(
411-
new BrSwitchBuilder(IGF, Subject, NumCases));
412-
case 2:
413-
// Two reachable destinations. We can emit a single conditional branch.
414-
return std::unique_ptr<SwitchBuilder>(
415-
new CondBrSwitchBuilder(IGF, Subject, Default, NumCases));
416-
default:
417-
// Anything more, fall over into a switch.
418-
// TODO: Since fast isel doesn't support switch insns, we may want to
419-
// also support a "pre-lowered-switch" builder that builds a jump tree
420-
// for unoptimized builds.
421-
return std::unique_ptr<SwitchBuilder>(
422-
new SwitchSwitchBuilder(IGF, Subject, Default, NumCases));
423-
}
424-
}
425-
426243
/// Implementation strategy for singleton enums, with zero or one cases.
427244
class SingletonEnumImplStrategy final : public EnumImplStrategy {
428245
bool needsPayloadSizeInMetadata() const override { return false; }

lib/IRGen/GenEnum.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#ifndef __SWIFT_IRGen_GenEnum_H__
14-
#define __SWIFT_IRGen_GenEnum_H__
13+
#ifndef SWIFT_IRGEN_GENENUM_H
14+
#define SWIFT_IRGEN_GENENUM_H
1515

1616
#include "TypeInfo.h"
1717

lib/IRGen/SwiftTargetInfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18-
#ifndef __SWIFT_IRGEN_TARGET_INFO_H__
19-
#define __SWIFT_IRGEN_TARGET_INFO_H__
18+
#ifndef SWIFT_IRGEN_SWIFTTARGETINFO_H
19+
#define SWIFT_IRGEN_SWIFTTARGETINFO_H
2020

2121
#include "swift/Basic/LLVM.h"
2222
#include "swift/Basic/ClusteredBitVector.h"

0 commit comments

Comments
 (0)