Speculative loads and alignment

Hi,

There are several optimizations where we try to load speculatively. There are also two similar functions to determine whether it's a safe transformation:
* isSafeToLoadUnconditionally
* isSafeToSpeculativelyExecute

isSafeToLoadUnconditionally tries to take load alignment into account but fails to do this in some cases. It checks alignment for pointers derived from allocas and global variables. But in other cases it scans the local BB to see if the pointer is already being loaded or stored from/to. In the latter case there can be a load/store with an alignment smaller than requested.

In most cases this function is used in conjunction with isDereferenceablePointer: isDereferenceablePointer || isSafeToLoadUnconditionally. So if a pointer is dereferenceable there will be no alignment check.

isSafeToSpeculativelyExecute doesn't care about alignment at all. It only checks for pointer dereferenceability. However according to the description it must check for undefined behavior which misaligned load (pointer alignment < instruction specified alignment) is.

Is it safe to load speculatively if we can't prove that the load is well-aligned (pointer alignment >= instruction specified alignment)?

Thanks,
Artur

From: "Artur Pilipenko" <apilipenko@azulsystems.com>
To: llvmdev@cs.uiuc.edu
Sent: Friday, April 24, 2015 11:51:08 AM
Subject: [LLVMdev] Speculative loads and alignment

Hi,

There are several optimizations where we try to load speculatively.
There are also two similar functions to determine whether it's a
safe transformation:
* isSafeToLoadUnconditionally
* isSafeToSpeculativelyExecute

isSafeToLoadUnconditionally tries to take load alignment into account
but fails to do this in some cases. It checks alignment for pointers
derived from allocas and global variables. But in other cases it
scans the local BB to see if the pointer is already being loaded or
stored from/to. In the latter case there can be a load/store with an
alignment smaller than requested.

In most cases this function is used in conjunction with
isDereferenceablePointer: isDereferenceablePointer ||
isSafeToLoadUnconditionally. So if a pointer is dereferenceable
there will be no alignment check.

isSafeToSpeculativelyExecute doesn't care about alignment at all. It
only checks for pointer dereferenceability. However according to the
description it must check for undefined behavior which misaligned
load (pointer alignment < instruction specified alignment) is.

Is it safe to load speculatively if we can't prove that the load is
well-aligned (pointer alignment >= instruction specified alignment)?

No, it is not safe (at least not without pessimizing the alignment); as you point out, the alignment can have control dependencies. Sounds like we should fix this (part of this fix should also be to update Clang to emit align attributes where it emits dereferenceable to preserve current optimizations).

-Hal

Hi Hal,

One more related question. If alignment is not specified for globals or allocas isSafeToLoadUnconditionally assumes that default alignment is what DataLayout::getPrefTypeAlignment returns. I can’t find any confirmation for this in docs. For globals I see:
“ If not present, or if the alignment is set to zero, the alignment of the global is set by the target to whatever it feels convenient.”
For allocas:
"If not specified, or if zero, the target can choose to align the allocation on any convenient boundary compatible with the type.”

Am I missing something? Is it correct assumption?

Thanks,
Artur

Hi Artur,

I apologize for the delay in responding; my understanding is that the alignment returned by getPrefTypeAlignment (the preferred stack/global alignment) is currently supposed to be that alignment that the target will find convenient.

At least for allocas, this is explicitly true. SelectionDAGBuilder::visitAlloca has this:

  unsigned Align =
      std::max((unsigned)TLI.getDataLayout()->getPrefTypeAlignment(Ty),
               I.getAlignment());

I'm not sure exactly what alignment we use for globals in this case. Rafael, do you know?

-Hal