diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 5ab6953bdbd..88c8ed42e6c 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -2885,7 +2885,13 @@ void AssemblyWriter::printInstruction(const Instruction &I) { if (AI->isUsedWithInAlloca()) Out << "inalloca "; TypePrinter.print(AI->getAllocatedType(), Out); - if (!AI->getArraySize() || AI->isArrayAllocation()) { + + // Explicitly write the array size if the code is broken, if it's an array + // allocation, or if the type is not canonical for scalar allocations. The + // latter case prevents the type from mutating when round-tripping through + // assembly. + if (!AI->getArraySize() || AI->isArrayAllocation() || + !AI->getArraySize()->getType()->isIntegerTy(32)) { Out << ", "; writeOperand(AI->getArraySize(), true); } diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index b19d2396585..a44a8deda1a 100644 --- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -165,6 +165,10 @@ isOnlyCopiedFromConstantGlobal(AllocaInst *AI, } static Instruction *simplifyAllocaArraySize(InstCombiner &IC, AllocaInst &AI) { + // Check for array size of 1 (scalar allocation). + if (!AI.isArrayAllocation()) + return nullptr; + // Ensure that the alloca array size argument has type intptr_t, so that // any casting is exposed early. Type *IntPtrTy = IC.getDataLayout().getIntPtrType(AI.getType()); @@ -174,10 +178,6 @@ static Instruction *simplifyAllocaArraySize(InstCombiner &IC, AllocaInst &AI) { return &AI; } - // Check C != 1 - if (!AI.isArrayAllocation()) - return nullptr; - // Convert: alloca Ty, C - where C is a constant != 1 into: alloca [C x Ty], 1 if (const ConstantInt *C = dyn_cast(AI.getArraySize())) { Type *NewTy = ArrayType::get(AI.getAllocatedType(), C->getZExtValue()); diff --git a/test/Assembler/alloca-size-one.ll b/test/Assembler/alloca-size-one.ll new file mode 100644 index 00000000000..fc5ee34254a --- /dev/null +++ b/test/Assembler/alloca-size-one.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s +; RUN: verify-uselistorder %s + +define void @foo() { +entry: +; CHECK: %alloc32 = alloca i1, align 8 +; CHECK: %alloc64 = alloca i1, i64 1, align 8 + %alloc32 = alloca i1, i32 1, align 8 + %alloc64 = alloca i1, i64 1, align 8 + unreachable +} diff --git a/test/Transforms/InstCombine/alloca.ll b/test/Transforms/InstCombine/alloca.ll index 105029fb699..db26218f3b8 100644 --- a/test/Transforms/InstCombine/alloca.ll +++ b/test/Transforms/InstCombine/alloca.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -instcombine -S -default-data-layout="E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" | FileCheck %s -; RUN: opt < %s -instcombine -S -default-data-layout="E-p:32:32:32-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" | FileCheck %s -check-prefix=P32 -; RUN: opt < %s -instcombine -S | FileCheck %s -check-prefix=NODL +; RUN: opt < %s -instcombine -S -default-data-layout="E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" | FileCheck %s -check-prefix=CHECK -check-prefix=ALL +; RUN: opt < %s -instcombine -S -default-data-layout="E-p:32:32:32-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" | FileCheck %s -check-prefix=P32 -check-prefix=ALL +; RUN: opt < %s -instcombine -S | FileCheck %s -check-prefix=NODL -check-prefix=ALL declare void @use(...) @@ -150,3 +150,16 @@ entry: call void @llvm.stackrestore(i8* %inalloca.save) ret void } + +define void @test10() { +entry: +; ALL-LABEL: @test10( +; ALL: %v32 = alloca i1, align 8 +; ALL: %v64 = alloca i1, i64 1, align 8 +; ALL: %v33 = alloca i1, i33 1, align 8 + %v32 = alloca i1, align 8 + %v64 = alloca i1, i64 1, align 8 + %v33 = alloca i1, i33 1, align 8 + call void (...)* @use(i1* %v32, i1* %v64, i1* %v33) + ret void +}