Index: include/llvm/IR/DataLayout.h =================================================================== --- include/llvm/IR/DataLayout.h +++ include/llvm/IR/DataLayout.h @@ -419,6 +419,16 @@ /// \brief Returns the minimum ABI-required alignment for the specified type. unsigned getABITypeAlignment(Type *Ty) const; + /// Checks if a type is aligned to a single byte. + bool isUnaligned(Type *Ty) const { + return getABITypeAlignment(Ty) == 1; + } + + /// Checks if a type has an alignment greater than one byte. + bool isAligned(Type *Ty) const { + return getABITypeAlignment(Ty) > 1; + } + /// \brief Returns the minimum ABI-required alignment for an integer type of /// the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4137,13 +4137,16 @@ SDLoc dl = getCurSDLoc(); AtomicOrdering Order = I.getOrdering(); SyncScope::ID SSID = I.getSyncScopeID(); + const auto &DL = DAG.getDataLayout(); + Type *Ty = I.getType(); SDValue InChain = getRoot(); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType()); + EVT VT = TLI.getValueType(DL, Ty); - if (I.getAlignment() < VT.getSizeInBits() / 8) + if (DL.isAligned(Ty) && + I.getAlignment() < VT.getSizeInBits() / 8) report_fatal_error("Cannot generate unaligned atomic load"); MachineMemOperand *MMO = Index: test/CodeGen/AVR/unaligned-atomic-loads.ll =================================================================== --- /dev/null +++ test/CodeGen/AVR/unaligned-atomic-loads.ll @@ -0,0 +1,19 @@ +; RUN: llc -mattr=addsubiw < %s -march=avr | FileCheck %s + +; This verifies that the middle end can handle an unaligned atomic load. +; +; In the past, an assertion inside the SelectionDAGBuilder would always +; hit an assertion for unaligned loads and stores. + +%AtomicI16 = type { %CellI16, [0 x i8] } +%CellI16 = type { i16, [0 x i8] } + +; CHECK-LABEL: foo +; CHECK: ret +define void @foo(%AtomicI16* %self) { +start: + %a = getelementptr inbounds %AtomicI16, %AtomicI16* %self, i16 0, i32 0, i32 0 + load atomic i16, i16* %a seq_cst, align 1 + ret void +} +