Use unaligned instructions for simd struct member access (#3596)
This commit is contained in:
+2
-3
@@ -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))
|
||||
|
||||
+16
-6
@@ -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)
|
||||
|
||||
+3
-1
@@ -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}"
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user