From 3707ba80302b184c850ccdab2191650b75486742 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 31 Mar 2016 15:37:06 +0000 Subject: [PATCH] [PowerPC] Correctly compute 64-bit offsets in fast isel PPCSimplifyAddress contains this code: IntegerType *OffsetTy = ((VT == MVT::i32) ? Type::getInt32Ty(*Context) : Type::getInt64Ty(*Context)); to determine the type to be used for an index register, if one needs to be created. However, the "VT" here is the type of the data being loaded or stored, *not* the type of an address. This means that if a data element of type i32 is accessed using an index that does not not fit into 32 bits, a wrong address is computed here. Note that PPCFastISel is only ever used on 64-bit currently, so the type of an address is actually *always* MVT::i64. Other parts of the code, even in this same PPCSimplifyAddress routine, already rely on that fact. Thus, this patch changes the code to simply unconditionally use Type::getInt64Ty(*Context) as OffsetTy. llvm-svn: 265023 --- llvm/lib/Target/PowerPC/PPCFastISel.cpp | 11 +++++------ llvm/test/CodeGen/PowerPC/fast-isel-i64offset.ll | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/fast-isel-i64offset.ll diff --git a/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/llvm/lib/Target/PowerPC/PPCFastISel.cpp index 901a750..0f4dee3 100644 --- a/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -158,7 +158,7 @@ class PPCFastISel final : public FastISel { unsigned FP64LoadOpc = PPC::LFD); bool PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr); bool PPCComputeAddress(const Value *Obj, Address &Addr); - void PPCSimplifyAddress(Address &Addr, MVT VT, bool &UseOffset, + void PPCSimplifyAddress(Address &Addr, bool &UseOffset, unsigned &IndexReg); bool PPCEmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, bool IsZExt); @@ -428,7 +428,7 @@ bool PPCFastISel::PPCComputeAddress(const Value *Obj, Address &Addr) { // Fix up some addresses that can't be used directly. For example, if // an offset won't fit in an instruction field, we may need to move it // into an index register. -void PPCFastISel::PPCSimplifyAddress(Address &Addr, MVT VT, bool &UseOffset, +void PPCFastISel::PPCSimplifyAddress(Address &Addr, bool &UseOffset, unsigned &IndexReg) { // Check whether the offset fits in the instruction field. @@ -447,8 +447,7 @@ void PPCFastISel::PPCSimplifyAddress(Address &Addr, MVT VT, bool &UseOffset, } if (!UseOffset) { - IntegerType *OffsetTy = ((VT == MVT::i32) ? Type::getInt32Ty(*Context) - : Type::getInt64Ty(*Context)); + IntegerType *OffsetTy = Type::getInt64Ty(*Context); const ConstantInt *Offset = ConstantInt::getSigned(OffsetTy, (int64_t)(Addr.Offset)); IndexReg = PPCMaterializeInt(Offset, MVT::i64); @@ -517,7 +516,7 @@ bool PPCFastISel::PPCEmitLoad(MVT VT, unsigned &ResultReg, Address &Addr, // If necessary, materialize the offset into a register and use // the indexed form. Also handle stack pointers with special needs. unsigned IndexReg = 0; - PPCSimplifyAddress(Addr, VT, UseOffset, IndexReg); + PPCSimplifyAddress(Addr, UseOffset, IndexReg); // If this is a potential VSX load with an offset of 0, a VSX indexed load can // be used. @@ -653,7 +652,7 @@ bool PPCFastISel::PPCEmitStore(MVT VT, unsigned SrcReg, Address &Addr) { // If necessary, materialize the offset into a register and use // the indexed form. Also handle stack pointers with special needs. unsigned IndexReg = 0; - PPCSimplifyAddress(Addr, VT, UseOffset, IndexReg); + PPCSimplifyAddress(Addr, UseOffset, IndexReg); // If this is a potential VSX store with an offset of 0, a VSX indexed store // can be used. diff --git a/llvm/test/CodeGen/PowerPC/fast-isel-i64offset.ll b/llvm/test/CodeGen/PowerPC/fast-isel-i64offset.ll new file mode 100644 index 0000000..e184ce4 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/fast-isel-i64offset.ll @@ -0,0 +1,15 @@ +; RUN: llc -mtriple powerpc64-unknown-linux-gnu -fast-isel -O0 < %s | FileCheck %s + +; Verify that pointer offsets larger than 32 bits work correctly. + +define void @test(i32* %array) { +; CHECK-LABEL: test: +; CHECK: lis [[REG:[0-9]+]], 16383 +; CHECK: ori [[REG]], [[REG]], 65535 +; CHECK: sldi [[REG]], [[REG]], 3 +; CHECK: stwx {{[0-9]+}}, 3, [[REG]] + %element = getelementptr i32, i32* %array, i64 2147483646 + store i32 1234, i32* %element + ret void +} + -- 2.7.4