Swift Optimizer: constant fold builtins in the simplification passes

This commit is contained in:
Erik Eckstein
2023-05-08 12:08:10 +02:00
parent 88973a3cd5
commit 9b51e69dac
8 changed files with 43 additions and 5 deletions

View File

@@ -23,8 +23,9 @@ extension BuiltinInst : OnoneSimplifyable {
case .IsSameMetatype:
optimizeIsSameMetatype(context)
default:
// TODO: handle other builtin types
break
if let literal = constantFold(context) {
uses.replaceAll(with: literal, context)
}
}
}
}

View File

@@ -283,6 +283,12 @@ extension Instruction {
}
}
extension BuiltinInst {
func constantFold(_ context: some MutatingContext) -> Value? {
context._bridged.constantFoldBuiltin(bridged).value
}
}
extension RefCountingInst {
func setAtomicity(isAtomic: Bool, _ context: some MutatingContext) {
context.notifyInstructionsChanged()

View File

@@ -202,5 +202,5 @@ final class PlaceholderValue : Value {
}
extension OptionalBridgedValue {
var value: Value? { obj.getAs(AnyObject.self) as? Value }
public var value: Value? { obj.getAs(AnyObject.self) as? Value }
}

View File

@@ -202,6 +202,9 @@ struct BridgedPassContext {
bool tryDeleteDeadClosure(BridgedInstruction closure) const;
SWIFT_IMPORT_UNSAFE
OptionalBridgedValue constantFoldBuiltin(BridgedInstruction builtin) const;
SWIFT_IMPORT_UNSAFE
BridgedValue getSILUndef(swift::SILType type) const {
return {swift::SILUndef::get(type, *invocation->getFunction())};

View File

@@ -52,6 +52,10 @@ APInt constantFoldDiv(APInt lhs, APInt rhs, bool &Overflow, BuiltinValueKind ID)
/// The \p ID must be the ID of a trunc/sext/zext builtin.
APInt constantFoldCast(APInt val, const BuiltinInfo &BI);
/// If `ResultsInError` is not none than errors are diagnosed and
/// `ResultsInError` is set to true in case of an error.
SILValue constantFoldBuiltin(BuiltinInst *BI,
Optional<bool> &ResultsInError);
/// A utility class to do constant folding.
class ConstantFolder {

View File

@@ -27,6 +27,7 @@
#include "swift/SILOptimizer/OptimizerBridging.h"
#include "swift/SILOptimizer/PassManager/PrettyStackTrace.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/ConstantFolding.h"
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
#include "swift/SILOptimizer/Utils/OptimizerStatsUtils.h"
#include "swift/SILOptimizer/Utils/StackNesting.h"
@@ -1420,6 +1421,12 @@ bool BridgedPassContext::tryDeleteDeadClosure(BridgedInstruction closure) const
return ::tryDeleteDeadClosure(closure.getAs<SingleValueInstruction>(), InstModCallbacks());
}
OptionalBridgedValue BridgedPassContext::constantFoldBuiltin(BridgedInstruction builtin) const {
auto bi = builtin.getAs<BuiltinInst>();
Optional<bool> resultsInError;
return {::constantFoldBuiltin(bi, resultsInError)};
}
void BridgedPassContext::fixStackNesting(BridgedFunction function) const {
switch (StackNesting::fixNesting(function.getFunction())) {
case StackNesting::Changes::None:

View File

@@ -566,7 +566,7 @@ static SILValue constantFoldBinary(BuiltinInst *BI,
Optional<bool> &ResultsInError) {
switch (ID) {
default:
llvm_unreachable("Not all BUILTIN_BINARY_OPERATIONs are covered!");
return nullptr;
// Not supported yet (not easily computable for APInt).
case BuiltinValueKind::ExactSDiv:
@@ -1134,7 +1134,7 @@ static SILValue constantFoldIsConcrete(BuiltinInst *BI) {
return inst;
}
static SILValue constantFoldBuiltin(BuiltinInst *BI,
SILValue swift::constantFoldBuiltin(BuiltinInst *BI,
Optional<bool> &ResultsInError) {
const IntrinsicInfo &Intrinsic = BI->getIntrinsicInfo();
SILModule &M = BI->getModule();

View File

@@ -24,6 +24,23 @@ class C1<T> {
class C2<T> : C1<T> {
}
// CHECK-LABEL: sil @constantFoldAdd
// CHECK: [[A:%.*]] = integer_literal $Builtin.Int64, 12
// CHECK: [[C:%.*]] = integer_literal $Builtin.Int1, 0
// CHECK: [[T:%.*]] = tuple ([[A]] : $Builtin.Int64, [[C]] : $Builtin.Int1)
// CHECK: [[R:%.*]] = tuple_extract [[T]] : $(Builtin.Int64, Builtin.Int1), 0
// CHECK: return [[R]]
// CHECK: } // end sil function 'constantFoldAdd'
sil @constantFoldAdd : $@convention(thin) () -> Builtin.Int64 {
bb0:
%0 = integer_literal $Builtin.Int64, 10
%1 = integer_literal $Builtin.Int64, 2
%2 = integer_literal $Builtin.Int1, 1
%3 = builtin "sadd_with_overflow_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
return %4 : $Builtin.Int64
}
// CHECK-LABEL: sil @isConcrete_true
// CHECK: bb0(%0 : $@thin Int.Type):
// CHECK: [[R:%.*]] = integer_literal $Builtin.Int1, -1