From 95365ca482c338634fdbc0a6c8176c52ad8bc7c6 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 27 Jul 2015 18:31:03 +0000 Subject: [PATCH] Fix assert when inlining a constantexpr addrspacecast The pointer size of the addrspacecasted pointer might not have matched, so this would have hit an assert in accumulateConstantOffset. I think this was here to allow constant folding of a load of an addrspacecasted constant. Accumulating the offset through the addrspacecast doesn't make much sense, so something else is necessary to allow folding the load through this cast. llvm-svn: 243300 --- llvm/lib/Analysis/ConstantFolding.cpp | 3 +- llvm/test/Transforms/ConstProp/loads.ll | 7 +++-- ...inline-constexpr-addrspacecast-argument.ll | 30 +++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 70c929b53a3f..07f53bedc776 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -248,8 +248,7 @@ static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, // Look through ptr->int and ptr->ptr casts. if (CE->getOpcode() == Instruction::PtrToInt || - CE->getOpcode() == Instruction::BitCast || - CE->getOpcode() == Instruction::AddrSpaceCast) + CE->getOpcode() == Instruction::BitCast) return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, DL); // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) diff --git a/llvm/test/Transforms/ConstProp/loads.ll b/llvm/test/Transforms/ConstProp/loads.ll index 5426ad0f8adb..89387ad06ba8 100644 --- a/llvm/test/Transforms/ConstProp/loads.ll +++ b/llvm/test/Transforms/ConstProp/loads.ll @@ -40,13 +40,16 @@ define i16 @test2_addrspacecast() { %r = load i16, i16 addrspace(1)* addrspacecast(i32* getelementptr ({{i32,i8},i32}, {{i32,i8},i32}* @g1, i32 0, i32 0, i32 0) to i16 addrspace(1)*) ret i16 %r +; FIXME: Should be able to load through a constant addrspacecast. ; 0xBEEF ; LE-LABEL: @test2_addrspacecast( -; LE: ret i16 -16657 +; XLE: ret i16 -16657 +; LE: load i16, i16 addrspace(1)* addrspacecast ; 0xDEAD ; BE-LABEL: @test2_addrspacecast( -; BE: ret i16 -8531 +; XBE: ret i16 -8531 +; BE: load i16, i16 addrspace(1)* addrspacecast } ; Load of second 16 bits of 32-bit value. diff --git a/llvm/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll b/llvm/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll new file mode 100644 index 000000000000..498a995ecd45 --- /dev/null +++ b/llvm/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll @@ -0,0 +1,30 @@ +; RUN: opt -S -inline < %s | FileCheck %s + +target datalayout = "e-p3:32:32-p4:64:64-n32" + +@lds = internal addrspace(3) global [64 x i64] zeroinitializer + +; CHECK-LABEL: @constexpr_addrspacecast_ptr_size_change( +; CHECK: load i64, i64 addrspace(4)* getelementptr (i64, i64 addrspace(4)* addrspacecast (i64 addrspace(3)* getelementptr inbounds ([64 x i64], [64 x i64] addrspace(3)* @lds, i32 0, i32 0) to i64 addrspace(4)*), i64 undef) +; CHECK-NEXT: br +define void @constexpr_addrspacecast_ptr_size_change() #0 { + %tmp0 = call i32 @foo(i64 addrspace(4)* addrspacecast (i64 addrspace(3)* getelementptr inbounds ([64 x i64], [64 x i64] addrspace(3)* @lds, i32 0, i32 0) to i64 addrspace(4)*)) #1 + ret void +} + +define i32 @foo(i64 addrspace(4)* %arg) #1 { +bb: + %tmp = getelementptr i64, i64 addrspace(4)* %arg, i64 undef + %tmp1 = load i64, i64 addrspace(4)* %tmp + br i1 undef, label %bb2, label %bb3 + +bb2: + store i64 0, i64 addrspace(4)* %tmp + br label %bb3 + +bb3: + unreachable +} + +attributes #0 = { nounwind } +attributes #1 = { alwaysinline nounwind }