Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ struct LifetimeDependence : CustomStringConvertible {
var parentValue: Value { scope.parentValue }

var function: Function {
dependentValue.parentFunction // dependentValue can't be undef
dependentValue.parentFunction
}

var description: String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ extension Value {
/// check, because it treats a value_to_bridge_object instruction as "trivial".
/// It can also handle non-trivial enums with trivial cases.
func isTrivial(_ context: some Context) -> Bool {
if self is Undef {
return true
}
var worklist = ValueWorklist(context)
defer { worklist.deinitialize() }

Expand All @@ -64,12 +61,12 @@ extension Value {
switch v {
case is ValueToBridgeObjectInst:
break
case is StructInst, is TupleInst:
let inst = (v as! SingleValueInstruction)
worklist.pushIfNotVisited(contentsOf: inst.operands.values.filter { !($0 is Undef) })
case let si as StructInst:
worklist.pushIfNotVisited(contentsOf: si.operands.values)
case let ti as TupleInst:
worklist.pushIfNotVisited(contentsOf: ti.operands.values)
case let en as EnumInst:
if let payload = en.payload,
!(payload is Undef) {
if let payload = en.payload {
worklist.pushIfNotVisited(payload)
}
default:
Expand Down
16 changes: 13 additions & 3 deletions SwiftCompilerSources/Sources/SIL/Value.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ public protocol Value : AnyObject, CustomStringConvertible {
var definingInstruction: Instruction? { get }

/// The block where the value is defined.
///
/// It's not legal to get the definingBlock of an `Undef` value.
var parentBlock: BasicBlock { get }

/// The function where the value lives in.
///
/// It's not legal to get the parentFunction of an instruction in a global initializer.
var parentFunction: Function { get }

/// True if the value has a trivial type.
var hasTrivialType: Bool { get }

Expand Down Expand Up @@ -113,6 +116,7 @@ extension Value {

public var uses: UseList { UseList(bridged.getFirstUse()) }

// Default implementation for all values which have a parent block, like instructions and arguments.
public var parentFunction: Function { parentBlock.parentFunction }

public var type: Type { bridged.getType().type }
Expand Down Expand Up @@ -206,8 +210,11 @@ extension BridgedValue {
public final class Undef : Value {
public var definingInstruction: Instruction? { nil }

public var parentFunction: Function { bridged.SILUndef_getParentFunction().function }

public var parentBlock: BasicBlock {
fatalError("undef has no defining block")
// By convention, undefs are considered to be defined at the entry of the function.
parentFunction.entryBlock
}

/// Undef has not parent function, therefore the default `hasTrivialType` does not work.
Expand All @@ -221,9 +228,12 @@ public final class Undef : Value {

final class PlaceholderValue : Value {
public var definingInstruction: Instruction? { nil }

public var parentBlock: BasicBlock {
fatalError("PlaceholderValue has no defining block")
}

public var parentFunction: Function { bridged.PlaceholderValue_getParentFunction().function }
}

extension OptionalBridgedValue {
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SIL/SILBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ struct BridgedValue {
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedOperand getFirstUse() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getType() const;
BRIDGED_INLINE Ownership getOwnership() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedFunction SILUndef_getParentFunction() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedFunction PlaceholderValue_getParentFunction() const;

bool findPointerEscape() const;
};
Expand Down
8 changes: 8 additions & 0 deletions include/swift/SIL/SILBridgingImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,14 @@ BridgedValue::Ownership BridgedValue::getOwnership() const {
return castOwnership(getSILValue()->getOwnershipKind());
}

BridgedFunction BridgedValue::SILUndef_getParentFunction() const {
return {llvm::cast<swift::SILUndef>(getSILValue())->getParent()};
}

BridgedFunction BridgedValue::PlaceholderValue_getParentFunction() const {
return {llvm::cast<swift::PlaceholderValue>(getSILValue())->getParent()};
}

//===----------------------------------------------------------------------===//
// BridgedOperand
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 1 addition & 3 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,9 +592,7 @@ SILCloner<ImplClass>::getMappedValue(SILValue Value) {
// If we have undef, just remap the type.
if (auto *U = dyn_cast<SILUndef>(Value)) {
auto type = getOpType(U->getType());
ValueBase *undef =
(type == U->getType() ? U : SILUndef::get(Builder.getFunction(), type));
return SILValue(undef);
return SILUndef::get(Builder.getFunction(), type);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! Thanks!

}

llvm_unreachable("Unmapped value while cloning?");
Expand Down
4 changes: 4 additions & 0 deletions lib/SIL/IR/SILValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ SILBasicBlock *SILNode::getParentBlock() const {
if (auto *MVR = dyn_cast<MultipleValueInstructionResult>(this)) {
return MVR->getParent()->getParent();
}
if (auto *undef = dyn_cast<SILUndef>(this)) {
// By convention, undefs are considered to be defined at the entry of the function.
return undef->getParent()->getEntryBlock();
}
return nullptr;
}

Expand Down
4 changes: 4 additions & 0 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,10 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"instruction isn't dominated by its bb argument operand");
}

if (auto *undef = dyn_cast<SILUndef>(operand.get())) {
require(undef->getParent() == BB->getParent(), "SILUndef in wrong function");
}

require(operand.getUser() == I,
"instruction's operand's owner isn't the instruction");
require(isOperandInValueUses(&operand), "operand value isn't used by operand");
Expand Down
8 changes: 4 additions & 4 deletions test/SILOptimizer/simplify_cfg_args.sil
Original file line number Diff line number Diff line change
Expand Up @@ -745,14 +745,14 @@ enum ThreeWay {

// CHECK-LABEL: sil hidden [noinline] @testUnwrapEnumArg : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK: br bb1(undef : $Builtin.Int64, %{{.*}} : $Payload)
// CHECK: bb1(%{{.*}} : $Builtin.Int64, %{{.*}} : $Payload):
// CHECK: br bb1(%{{.*}} : $Payload)
// CHECK: bb1(%{{.*}} : $Payload):
// CHECK: alloc_stack $Payload
// CHECK: switch_enum undef : $ThreeWay, case #ThreeWay.one!enumelt: bb4, case #ThreeWay.two!enumelt: bb2, case #ThreeWay.three!enumelt: bb3
// CHECK: bb2:
// CHECK: [[P2:%.*]] = load %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
// CHECK: br bb1(undef : $Builtin.Int64, [[P2]] : $Payload)
// CHECK: br bb1([[P2]] : $Payload)
// CHECK: bb3:
// CHECK: [[P3:%.*]] = load %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
Expand All @@ -764,7 +764,7 @@ enum ThreeWay {
// CHECK: bb5:
// CHECK: br bb7
// CHECK: bb6:
// CHECK: br bb1(undef : $Builtin.Int64, [[P4]] : $Payload)
// CHECK: br bb1([[P4]] : $Payload)
// CHECK: bb7:
// CHECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function 'testUnwrapEnumArg'
Expand Down
8 changes: 4 additions & 4 deletions test/SILOptimizer/simplify_cfg_args_ossa.sil
Original file line number Diff line number Diff line change
Expand Up @@ -723,14 +723,14 @@ enum ThreeWay {

// CHECK-LABEL: sil hidden [noinline] [ossa] @testUnwrapEnumArg : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK: br bb1(undef : $Builtin.Int64, %{{.*}} : $Payload)
// CHECK: bb1(%{{.*}} : $Builtin.Int64, %{{.*}} : $Payload):
// CHECK: br bb1(%{{.*}} : $Payload)
// CHECK: bb1(%{{.*}} : $Payload):
// CHECK: alloc_stack $Payload
// CHECK: switch_enum undef : $ThreeWay, case #ThreeWay.one!enumelt: bb4, case #ThreeWay.two!enumelt: bb2, case #ThreeWay.three!enumelt: bb3
// CHECK: bb2:
// CHECK: [[P2:%.*]] = load [trivial] %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
// CHECK: br bb1(undef : $Builtin.Int64, [[P2]] : $Payload)
// CHECK: br bb1([[P2]] : $Payload)
// CHECK: bb3:
// CHECK: [[P3:%.*]] = load [trivial] %{{.*}} : $*Payload
// CHECK: dealloc_stack %{{.*}} : $*Payload
Expand All @@ -740,7 +740,7 @@ enum ThreeWay {
// CHECK: dealloc_stack %{{.*}} : $*Payload
// CHECK: cond_br undef, bb6, bb5
// CHECK: bb5:
// CHECK: br bb1(undef : $Builtin.Int64, [[P4]] : $Payload)
// CHECK: br bb1([[P4]] : $Payload)
// CHECK: bb6:
// CHECK: br bb7
// CHECK: bb7:
Expand Down