Skip to content
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/Instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ class LoadInst : public UnaryInstruction {
!isVolatile();
}

/// Returns false if this type would be invalid in the
/// creation of a load atomic instruction.
static bool isValidAtomicTy(Type *Ty, const DataLayout *DL = nullptr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DataLayout must be mandatory

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we need to omit it entirely because otherwise we will be checking the type size of the alloca, which we want to avoid if to optimize basictest.ll.

AtomicOrdering AO = AtomicOrdering::NotAtomic);

Value *getPointerOperand() { return getOperand(0); }
const Value *getPointerOperand() const { return getOperand(0); }
static unsigned getPointerOperandIndex() { return 0U; }
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/IR/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,20 @@ void LoadInst::AssertOK() {
"Ptr must have pointer type.");
}

bool LoadInst::isValidAtomicTy(Type *Ty, const DataLayout *DL,
AtomicOrdering AO) {
// TODO: Share methods with IR/Verifier.
if (!Ty->isIntOrPtrTy() && !Ty->isFloatingPointTy())
return false;
if (AO == AtomicOrdering::Release || AO == AtomicOrdering::AcquireRelease)
return false;
if (DL) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mandatory

unsigned Size = DL->getTypeSizeInBits(Ty);
return Size >= 8 && !(Size & (Size - 1));
}
return true;
}

static Align computeLoadStoreDefaultAlign(Type *Ty, InsertPosition Pos) {
assert(Pos.isValid() &&
"Insertion position cannot be null when alignment not provided!");
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/Scalar/SROA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2853,6 +2853,12 @@ class AllocaSliceRewriter : public InstVisitor<AllocaSliceRewriter, bool> {

bool visitLoadInst(LoadInst &LI) {
LLVM_DEBUG(dbgs() << " original: " << LI << "\n");

// Load atomic vector would be generated, which is illegal.
// TODO: Generate a generic bitcast in machine codegen instead.
if (LI.isAtomic() && !LoadInst::isValidAtomicTy(NewAI.getAllocatedType()))
return false;

Value *OldOp = LI.getOperand(0);
assert(OldOp == OldPtr);

Expand All @@ -2875,6 +2881,7 @@ class AllocaSliceRewriter : public InstVisitor<AllocaSliceRewriter, bool> {
(canConvertValue(DL, NewAllocaTy, TargetTy) ||
(IsLoadPastEnd && NewAllocaTy->isIntegerTy() &&
TargetTy->isIntegerTy() && !LI.isVolatile()))) {

Value *NewPtr =
getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
LoadInst *NewLI = IRB.CreateAlignedLoad(NewAI.getAllocatedType(), NewPtr,
Expand Down
70 changes: 70 additions & 0 deletions llvm/test/Transforms/SROA/atomic-vector.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes='sroa' -S | FileCheck %s

define float @atomic_vector() {
; CHECK-LABEL: define float @atomic_vector() {
; CHECK-NEXT: [[TMP1:%.*]] = alloca <1 x float>, align 4
; CHECK-NEXT: store <1 x float> undef, ptr [[TMP1]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = load atomic volatile float, ptr [[TMP1]] acquire, align 4
; CHECK-NEXT: ret float [[TMP2]]
;
%src = alloca <1 x float>
%val = alloca <1 x float>
%direct = alloca ptr
call void @llvm.memcpy.p0.p0.i64(ptr %val, ptr %src, i64 4, i1 false)
store ptr %val, ptr %direct
%indirect = load ptr, ptr %direct
%ret = load atomic volatile float, ptr %indirect acquire, align 4
ret float %ret
}

define i32 @atomic_vector_int() {
; CHECK-LABEL: define i32 @atomic_vector_int() {
; CHECK-NEXT: [[VAL:%.*]] = alloca <1 x i32>, align 4
; CHECK-NEXT: store <1 x i32> undef, ptr [[VAL]], align 4
; CHECK-NEXT: [[RET:%.*]] = load atomic volatile i32, ptr [[VAL]] acquire, align 4
; CHECK-NEXT: ret i32 [[RET]]
;
%src = alloca <1 x i32>
%val = alloca <1 x i32>
%direct = alloca ptr
call void @llvm.memcpy.p0.p0.i64(ptr %val, ptr %src, i64 4, i1 false)
store ptr %val, ptr %direct
%indirect = load ptr, ptr %direct
%ret = load atomic volatile i32, ptr %indirect acquire, align 4
ret i32 %ret
}

define ptr @atomic_vector_ptr() {
; CHECK-LABEL: define ptr @atomic_vector_ptr() {
; CHECK-NEXT: [[VAL_SROA_0:%.*]] = alloca <1 x ptr>, align 8
; CHECK-NEXT: store <1 x ptr> undef, ptr [[VAL_SROA_0]], align 8
; CHECK-NEXT: [[VAL_SROA_0_0_VAL_SROA_0_0_RET:%.*]] = load atomic volatile ptr, ptr [[VAL_SROA_0]] acquire, align 4
; CHECK-NEXT: ret ptr [[VAL_SROA_0_0_VAL_SROA_0_0_RET]]
;
%src = alloca <1 x ptr>
%val = alloca <1 x ptr>
%direct = alloca ptr
call void @llvm.memcpy.p0.p0.i64(ptr %val, ptr %src, i64 8, i1 false)
store ptr %val, ptr %direct
%indirect = load ptr, ptr %direct
%ret = load atomic volatile ptr, ptr %indirect acquire, align 4
ret ptr %ret
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test a <2 x i16> or some other real vector. 1 x is a degenerate case


define i32 @atomic_2vector_int() {
; CHECK-LABEL: define i32 @atomic_2vector_int() {
; CHECK-NEXT: [[VAL_SROA_0:%.*]] = alloca i32, align 8
; CHECK-NEXT: store i32 undef, ptr [[VAL_SROA_0]], align 8
; CHECK-NEXT: [[VAL_SROA_0_0_VAL_SROA_0_0_RET:%.*]] = load atomic volatile i32, ptr [[VAL_SROA_0]] acquire, align 4
; CHECK-NEXT: ret i32 [[VAL_SROA_0_0_VAL_SROA_0_0_RET]]
;
%src = alloca <2 x i32>
%val = alloca <2 x i32>
%direct = alloca ptr
call void @llvm.memcpy.p0.p0.i64(ptr %val, ptr %src, i64 4, i1 false)
store ptr %val, ptr %direct
%indirect = load ptr, ptr %direct
%ret = load atomic volatile i32, ptr %indirect acquire, align 4
ret i32 %ret
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add test for the non-byte illegal case?

Loading