Use unaligned instructions for simd struct member access (#3596)

This commit is contained in:
Vladimir Ivanov
2019-11-21 14:05:43 +03:00
committed by GitHub
parent ec6fa2dcd5
commit 1fea5cdac2
4 changed files with 49 additions and 13 deletions
@@ -318,13 +318,12 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
updateRef(value, ptr, onStack = true)
}
fun storeAny(value: LLVMValueRef, ptr: LLVMValueRef, onStack: Boolean) {
if (isObjectRef(value)) {
fun storeAny(value: LLVMValueRef, ptr: LLVMValueRef, onStack: Boolean) = if (isObjectRef(value)) {
if (onStack) storeStackRef(value, ptr) else storeHeapRef(value, ptr)
null
} else {
LLVMBuildStore(builder, value, ptr)
}
}
fun freeze(value: LLVMValueRef, exceptionHandler: ExceptionHandler) {
if (isObjectRef(value))
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -1476,15 +1477,15 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------//
private fun evaluateGetField(value: IrGetField): LLVMValueRef {
context.log{"evaluateGetField : ${ir2string(value)}"}
if (!value.symbol.owner.isStatic) {
context.log { "evaluateGetField : ${ir2string(value)}" }
return if (!value.symbol.owner.isStatic) {
val thisPtr = evaluateExpression(value.receiver!!)
return functionGenerationContext.loadSlot(
functionGenerationContext.loadSlot(
fieldPtrOfClass(thisPtr, value.symbol.owner), !value.symbol.owner.isFinal)
} else {
assert(value.receiver == null)
return if (value.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true) {
evaluateConst(value.symbol.owner.initializer?.expression as IrConst<*>)
if (value.symbol.owner.correspondingPropertySymbol?.owner?.isConst == true) {
evaluateConst(value.symbol.owner.initializer?.expression as IrConst<*>)
} else {
if (context.config.threadsAreAllowed && value.symbol.owner.isMainOnlyNonPrimitive) {
functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler)
@@ -1492,6 +1493,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val ptr = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
functionGenerationContext.loadSlot(ptr, !value.symbol.owner.isFinal)
}
}.also {
if (value.type.classifierOrNull?.isClassWithFqName(vectorType) == true)
LLVMSetAlignment(it, 8)
}
}
@@ -1505,7 +1510,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun evaluateSetField(value: IrSetField): LLVMValueRef {
context.log{"evaluateSetField : ${ir2string(value)}"}
val valueToAssign = evaluateExpression(value.value)
if (!value.symbol.owner.isStatic) {
val store = if (!value.symbol.owner.isStatic) {
val thisPtr = evaluateExpression(value.receiver!!)
assert(thisPtr.type == codegen.kObjHeaderPtr) {
LLVMPrintTypeToString(thisPtr.type)?.toKString().toString()
@@ -1525,11 +1530,16 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler)
functionGenerationContext.storeAny(valueToAssign, globalValue, false)
}
if (store != null && value.value.type.classifierOrNull?.isClassWithFqName(vectorType) == true) {
LLVMSetAlignment(store, 8)
}
assert (value.type.isUnit())
return codegen.theUnitInstanceRef.llvm
}
private val vectorType = FqName("kotlin.native.Vector128").toUnsafe()
//-------------------------------------------------------------------------//
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef {
val fieldInfo = context.llvmDeclarations.forField(value)
@@ -24,7 +24,9 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
inner class SlotRecord(val address: LLVMValueRef, val refSlot: Boolean, val isVar: Boolean) : Record {
override fun load() : LLVMValueRef = functionGenerationContext.loadSlot(address, isVar)
override fun store(value: LLVMValueRef) = functionGenerationContext.storeAny(value, address, true)
override fun store(value: LLVMValueRef) {
functionGenerationContext.storeAny(value, address, true)
}
override fun address() : LLVMValueRef = this.address
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
}
+28 -3
View File
@@ -9,6 +9,8 @@ import kotlin.test.*
@Test fun runTest() {
testBoxingSimple()
testBoxing()
testSetGet()
testString()
testOOB()
@@ -17,19 +19,42 @@ import kotlin.test.*
testDefaultValue()
}
class Box<T>(t: T) {
var value = t
}
class UnalignedC(t: Vector128) {
var smth = 1
var value = t
}
fun testBoxingSimple() {
val v = vectorOf(1f, 3.162f, 10f, 31f)
val box: Box<Vector128> = Box<Vector128>(v)
assertEquals(v, box.value, "testBoxingSimple FAILED")
}
fun testBoxing() {
var u = UnalignedC(vectorOf(0, 1, 2, 3))
assertEquals(3, u.value.getIntAt(3))
u.value = vectorOf(0f, 1f, 2f, 3f)
assertEquals(vectorOf(0f, 1f, 2f, 3f), u.value, "testBoxing FAILED")
}
fun testSetGet() {
var v4any = vectorOf(0, 1, 2, 3)
(0 until 4).forEach { assertEquals(it, v4any.getIntAt(it)) }
(0 until 4).forEach { assertEquals(it, v4any.getIntAt(it), "testSetGet FAILED for <4 x i32>") }
// type punning: set the variable to another runtime type
val a = arrayOf(1f, 3.162f, 10f, 31f)
v4any = vectorOf(a[0], a[1], a[2], a[3])
(0 until 4).forEach { assertEquals(a[it], v4any.getFloatAt(it)) }
(0 until 4).forEach { assertEquals(a[it], v4any.getFloatAt(it), "testSetGet FAILED for <4 x float>") }
}
fun testString() {
val v4i = vectorOf(100, 1024, Int.MAX_VALUE, Int.MIN_VALUE)
assertEquals("(0x64, 0x400, 0x7fffffff, 0x80000000)", v4i.toString())
assertEquals("(0x64, 0x400, 0x7fffffff, 0x80000000)", v4i.toString(), "testString FAILED")
}
fun testOOB() {