diff --git a/compiler/optimizer/OMRTransformUtil.cpp b/compiler/optimizer/OMRTransformUtil.cpp index 9e279042b51..eab428667f8 100644 --- a/compiler/optimizer/OMRTransformUtil.cpp +++ b/compiler/optimizer/OMRTransformUtil.cpp @@ -454,7 +454,7 @@ OMR::TransformUtil::generateDataAddrLoadTrees(TR::Compilation *comp, TR::Node *a #endif /* OMR_GC_SPARSE_HEAP_ALLOCATION */ TR::Node * -OMR::TransformUtil::generateArrayElementAddressTrees(TR::Compilation *comp, TR::Node *arrayNode, TR::Node *offsetNode) +OMR::TransformUtil::generateArrayElementAddressTrees(TR::Compilation *comp, TR::Node *arrayNode, TR::Node *offsetNode, bool subNegativeHeaderSize) { TR::Node *arrayAddressNode = NULL; TR::Node *totalOffsetNode = NULL; @@ -470,22 +470,34 @@ OMR::TransformUtil::generateArrayElementAddressTrees(TR::Compilation *comp, TR:: if (offsetNode) arrayAddressNode = TR::Node::create(TR::aladd, 2, arrayAddressNode, offsetNode); } - else if (comp->target().is64Bit()) -#else - if (comp->target().is64Bit()) -#endif /* OMR_GC_SPARSE_HEAP_ALLOCATION */ - { - totalOffsetNode = TR::Node::lconst(TR::Compiler->om.contiguousArrayHeaderSizeInBytes()); - if (offsetNode) - totalOffsetNode = TR::Node::create(TR::ladd, 2, offsetNode, totalOffsetNode); - arrayAddressNode = TR::Node::create(TR::aladd, 2, arrayNode, totalOffsetNode); - } else +#endif /* OMR_GC_SPARSE_HEAP_ALLOCATION */ { - totalOffsetNode = TR::Node::iconst(static_cast(TR::Compiler->om.contiguousArrayHeaderSizeInBytes())); + TR_ASSERT_FATAL_WITH_NODE(arrayNode, + static_cast(TR::Compiler->om.contiguousArrayHeaderSizeInBytes()) <= TR::getMaxSigned(), + "Array header size is expected to fit in int32 but was wider.\n"); + TR::DataTypes widestAvailableIntDataType = comp->target().is64Bit() ? TR::DataTypes::Int64 : TR::DataTypes::Int32; + + int32_t arrayHeaderSize = static_cast(TR::Compiler->om.contiguousArrayHeaderSizeInBytes()); if (offsetNode) - totalOffsetNode = TR::Node::create(TR::iadd, 2, offsetNode, totalOffsetNode); - arrayAddressNode = TR::Node::create(TR::aiadd, 2, arrayNode, totalOffsetNode); + { + TR::ILOpCodes offsetNodeOpCode = TR::ILOpCode::addOpCode(widestAvailableIntDataType, comp->target().is64Bit()); + + if (subNegativeHeaderSize) + { + arrayHeaderSize = -arrayHeaderSize; + offsetNodeOpCode = TR::ILOpCode::subtractOpCode(widestAvailableIntDataType); + } + + totalOffsetNode = TR::Node::create(offsetNodeOpCode, 2, offsetNode, TR::Node::iconst(arrayHeaderSize)); + } + else + { + totalOffsetNode = TR::Node::iconst(arrayHeaderSize); + } + + TR::ILOpCodes arrayAddressNodeOpCode = TR::ILOpCode::addOpCode(TR::DataTypes::Address, comp->target().is64Bit()); + arrayAddressNode = TR::Node::create(arrayAddressNodeOpCode, 2, arrayNode, totalOffsetNode); } return arrayAddressNode; diff --git a/compiler/optimizer/OMRTransformUtil.hpp b/compiler/optimizer/OMRTransformUtil.hpp index c6b27032077..fe61db38af5 100644 --- a/compiler/optimizer/OMRTransformUtil.hpp +++ b/compiler/optimizer/OMRTransformUtil.hpp @@ -219,6 +219,10 @@ class OMR_EXTENSIBLE TransformUtil * \param offsetNode * The offset node (in bytes) * + * \param subNegativeHeaderSize + * Subtract -header size from offset instead of adding header size, + * applies only when offsetNode is not null + * * \return * IL to access array element at offset provided by offsetNode or * first array element if no offset node is provided @@ -226,7 +230,8 @@ class OMR_EXTENSIBLE TransformUtil static TR::Node *generateArrayElementAddressTrees( TR::Compilation *comp, TR::Node *arrayNode, - TR::Node *offsetNode = NULL); + TR::Node *offsetNode = NULL, + bool subNegativeHeaderSize = false); /** * \brief