From 9bd6b02f5cc4cadef798403663297a789c4b6cf4 Mon Sep 17 00:00:00 2001 From: David Zarzycki Date: Mon, 4 May 2020 07:03:02 -0400 Subject: [PATCH] [SILOpt] Add ZeroInitializer to isValidStaticInitializerInst --- lib/IRGen/GenConstant.cpp | 37 +++++++++++++++++++++ lib/IRGen/GenConstant.h | 3 ++ lib/SIL/IR/SILGlobalVariable.cpp | 6 ++++ test/SILOptimizer/zeroInitializer.swift | 44 +++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 test/SILOptimizer/zeroInitializer.swift diff --git a/lib/IRGen/GenConstant.cpp b/lib/IRGen/GenConstant.cpp index c8bd8efb530e0..6855b0ccadf94 100644 --- a/lib/IRGen/GenConstant.cpp +++ b/lib/IRGen/GenConstant.cpp @@ -56,6 +56,41 @@ llvm::Constant *irgen::emitConstantInt(IRGenModule &IGM, return llvm::ConstantInt::get(IGM.getLLVMContext(), value); } +llvm::Constant *irgen::emitConstantZero(IRGenModule &IGM, BuiltinInst *BI) { + assert(IGM.getSILModule().getBuiltinInfo(BI->getName()).ID == + BuiltinValueKind::ZeroInitializer); + + auto helper = [&](CanType astType) -> llvm::Constant * { + if (auto type = astType->getAs()) { + APInt zero(type->getWidth().getLeastWidth(), 0); + return llvm::ConstantInt::get(IGM.getLLVMContext(), zero); + } + + if (auto type = astType->getAs()) { + const llvm::fltSemantics *sema = nullptr; + switch (type->getFPKind()) { + case BuiltinFloatType::IEEE16: sema = &APFloat::IEEEhalf(); break; + case BuiltinFloatType::IEEE32: sema = &APFloat::IEEEsingle(); break; + case BuiltinFloatType::IEEE64: sema = &APFloat::IEEEdouble(); break; + case BuiltinFloatType::IEEE80: sema = &APFloat::x87DoubleExtended(); break; + case BuiltinFloatType::IEEE128: sema = &APFloat::IEEEquad(); break; + case BuiltinFloatType::PPC128: sema = &APFloat::PPCDoubleDouble(); break; + } + auto zero = APFloat::getZero(*sema); + return llvm::ConstantFP::get(IGM.getLLVMContext(), zero); + } + + llvm_unreachable("SIL allowed an unknown type?"); + }; + + if (auto vector = BI->getType().getAs()) { + auto zero = helper(vector.getElementType()); + return llvm::ConstantVector::getSplat(vector->getNumElements(), zero); + } + + return helper(BI->getType().getASTType()); +} + llvm::Constant *irgen::emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI) { return llvm::ConstantFP::get(IGM.getLLVMContext(), FLI->getValue()); } @@ -94,6 +129,8 @@ static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) { return emitAddrOfConstantString(IGM, SLI); } else if (auto *BI = dyn_cast(operand)) { switch (IGM.getSILModule().getBuiltinInfo(BI->getName()).ID) { + case BuiltinValueKind::ZeroInitializer: + return emitConstantZero(IGM, BI); case BuiltinValueKind::PtrToInt: { llvm::Constant *ptr = emitConstantValue(IGM, BI->getArguments()[0]); return llvm::ConstantExpr::getPtrToInt(ptr, IGM.IntPtrTy); diff --git a/lib/IRGen/GenConstant.h b/lib/IRGen/GenConstant.h index 3a5c23adb0911..faa67fcc8114f 100644 --- a/lib/IRGen/GenConstant.h +++ b/lib/IRGen/GenConstant.h @@ -27,6 +27,9 @@ namespace irgen { /// Construct a ConstantInt from an IntegerLiteralInst. llvm::Constant *emitConstantInt(IRGenModule &IGM, IntegerLiteralInst *ILI); +/// Construct a zero from a zero intializer BuiltinInst. +llvm::Constant *emitConstantZero(IRGenModule &IGM, BuiltinInst *Bi); + /// Construct a ConstantFP from a FloatLiteralInst. llvm::Constant *emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI); diff --git a/lib/SIL/IR/SILGlobalVariable.cpp b/lib/SIL/IR/SILGlobalVariable.cpp index 733ad528dcd52..a7473bbd287e6 100644 --- a/lib/SIL/IR/SILGlobalVariable.cpp +++ b/lib/SIL/IR/SILGlobalVariable.cpp @@ -109,6 +109,12 @@ bool SILGlobalVariable::isValidStaticInitializerInst(const SILInstruction *I, case SILInstructionKind::BuiltinInst: { auto *bi = cast(I); switch (M.getBuiltinInfo(bi->getName()).ID) { + case BuiltinValueKind::ZeroInitializer: { + auto type = bi->getType().getASTType(); + if (auto vector = dyn_cast(type)) + type = vector.getElementType(); + return isa(type) || isa(type); + } case BuiltinValueKind::PtrToInt: if (isa(bi->getArguments()[0])) return true; diff --git a/test/SILOptimizer/zeroInitializer.swift b/test/SILOptimizer/zeroInitializer.swift new file mode 100644 index 0000000000000..83b8f861c5f04 --- /dev/null +++ b/test/SILOptimizer/zeroInitializer.swift @@ -0,0 +1,44 @@ +// RUN: %target-swift-frontend -O -parse-stdlib -emit-ir -module-name ZeroInit -verify %s | %FileCheck %s + +import Swift + +@frozen +public struct TestInt { + @usableFromInline + var _value : Builtin.Int32 + @_transparent + public init() { + _value = Builtin.zeroInitializer() + } +} + +@frozen +public struct TestFloat { + @usableFromInline + var _value : Builtin.FPIEEE32 + @_transparent + public init() { + _value = Builtin.zeroInitializer() + } +} + +@frozen +public struct TestVector { + @usableFromInline + var _value : Builtin.Vec4xFPIEEE32 + @_transparent + public init() { + _value = Builtin.zeroInitializer() + } +} + +public struct Foo { + public static var x : TestInt = TestInt() + public static var y : TestFloat = TestFloat() + public static var z : TestVector = TestVector() +} + +// CHECK: @"$s8ZeroInit3FooV1xAA7TestIntVvpZ" ={{.*}} global %T8ZeroInit7TestIntV zeroinitializer +// CHECK: @"$s8ZeroInit3FooV1yAA9TestFloatVvpZ" ={{.*}} global %T8ZeroInit9TestFloatV zeroinitializer +// CHECK: @"$s8ZeroInit3FooV1zAA10TestVectorVvpZ" ={{.*}} global %T8ZeroInit10TestVectorV zeroinitializer +// CHECK-NOT: swift_once