From c8a1a3c426209e9c7b35e279e1578a89edc40af6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 8 Dec 2008 07:57:47 +0000 Subject: [PATCH] Factor out the code for sign-extending/truncating gep indices and use it in x86 address mode folding. Also, make getRegForValue return 0 for illegal types even if it has a ValueMap for them, because Argument values are put in the ValueMap. This fixes PR3181. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60696 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/FastISel.h | 5 +++ lib/CodeGen/SelectionDAG/FastISel.cpp | 55 +++++++++++++++----------- lib/Target/X86/X86FastISel.cpp | 6 +-- test/CodeGen/X86/fast-isel-gep-sext.ll | 17 ++++++++ 4 files changed, 57 insertions(+), 26 deletions(-) create mode 100644 test/CodeGen/X86/fast-isel-gep-sext.ll diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 71db9b58023..1cc83106052 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -106,6 +106,11 @@ public: /// defined locally. unsigned lookUpRegForValue(Value *V); + /// getRegForGEPIndex - This is a wrapper around getRegForValue that also + /// takes care of truncating or sign-extending the given getelementptr + /// index value. + unsigned getRegForGEPIndex(Value *V); + virtual ~FastISel(); protected: diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 037a46d382c..3d0348d5d11 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -55,19 +55,11 @@ using namespace llvm; unsigned FastISel::getRegForValue(Value *V) { - // Look up the value to see if we already have a register for it. We - // cache values defined by Instructions across blocks, and other values - // only locally. This is because Instructions already have the SSA - // def-dominatess-use requirement enforced. - if (ValueMap.count(V)) - return ValueMap[V]; - unsigned Reg = LocalValueMap[V]; - if (Reg != 0) - return Reg; - MVT::SimpleValueType VT = TLI.getValueType(V->getType()).getSimpleVT(); - // Ignore illegal types. + // Ignore illegal types. We must do this before looking up the value + // in ValueMap because Arguments are given virtual registers regardless + // of whether FastISel can handle them. if (!TLI.isTypeLegal(VT)) { // Promote MVT::i1 to a legal type though, because it's common and easy. if (VT == MVT::i1) @@ -76,6 +68,16 @@ unsigned FastISel::getRegForValue(Value *V) { return 0; } + // Look up the value to see if we already have a register for it. We + // cache values defined by Instructions across blocks, and other values + // only locally. This is because Instructions already have the SSA + // def-dominatess-use requirement enforced. + if (ValueMap.count(V)) + return ValueMap[V]; + unsigned Reg = LocalValueMap[V]; + if (Reg != 0) + return Reg; + if (ConstantInt *CI = dyn_cast(V)) { if (CI->getValue().getActiveBits() <= 64) Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue()); @@ -153,6 +155,24 @@ void FastISel::UpdateValueMap(Value* I, unsigned Reg) { Reg, MRI.getRegClass(Reg), MRI.getRegClass(Reg)); } +unsigned FastISel::getRegForGEPIndex(Value *Idx) { + unsigned IdxN = getRegForValue(Idx); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return 0; + + // If the index is smaller or larger than intptr_t, truncate or extend it. + MVT PtrVT = TLI.getPointerTy(); + MVT IdxVT = MVT::getMVT(Idx->getType(), /*HandleUnknown=*/false); + if (IdxVT.bitsLT(PtrVT)) + IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT.getSimpleVT(), + ISD::SIGN_EXTEND, IdxN); + else if (IdxVT.bitsGT(PtrVT)) + IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT.getSimpleVT(), + ISD::TRUNCATE, IdxN); + return IdxN; +} + /// SelectBinaryOp - Select and emit code for a binary operator instruction, /// which has an opcode which directly corresponds to the given ISD opcode. /// @@ -263,18 +283,7 @@ bool FastISel::SelectGetElementPtr(User *I) { // N = N + Idx * ElementSize; uint64_t ElementSize = TD.getABITypeSize(Ty); - unsigned IdxN = getRegForValue(Idx); - if (IdxN == 0) - // Unhandled operand. Halt "fast" selection and bail. - return false; - - // If the index is smaller or larger than intptr_t, truncate or extend - // it. - MVT IdxVT = MVT::getMVT(Idx->getType(), /*HandleUnknown=*/false); - if (IdxVT.bitsLT(VT)) - IdxN = FastEmit_r(IdxVT.getSimpleVT(), VT, ISD::SIGN_EXTEND, IdxN); - else if (IdxVT.bitsGT(VT)) - IdxN = FastEmit_r(IdxVT.getSimpleVT(), VT, ISD::TRUNCATE, IdxN); + unsigned IdxN = getRegForGEPIndex(Idx); if (IdxN == 0) // Unhandled operand. Halt "fast" selection and bail. return false; diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index b280d652901..04a26303dcf 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -372,8 +372,8 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) { unsigned IndexReg = AM.IndexReg; unsigned Scale = AM.Scale; gep_type_iterator GTI = gep_type_begin(U); - // Look at all but the last index. Constants can be folded, - // and one dynamic index can be handled, if the scale is supported. + // Iterate through the indices, folding what we can. Constants can be + // folded, and one dynamic index can be handled, if the scale is supported. for (User::op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; ++i, ++GTI) { Value *Op = *i; @@ -392,7 +392,7 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) { (S == 1 || S == 2 || S == 4 || S == 8)) { // Scaled-index addressing. Scale = S; - IndexReg = getRegForValue(Op); + IndexReg = getRegForGEPIndex(Op); if (IndexReg == 0) return false; } else diff --git a/test/CodeGen/X86/fast-isel-gep-sext.ll b/test/CodeGen/X86/fast-isel-gep-sext.ll new file mode 100644 index 00000000000..ec420ff0266 --- /dev/null +++ b/test/CodeGen/X86/fast-isel-gep-sext.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | llc -march=x86-64 -fast | grep movslq +; RUN: llvm-as < %s | llc -march=x86 -fast +; PR3181 + +; GEP indices are interpreted as signed integers, so they +; should be sign-extended to 64 bits on 64-bit targets. + +define i32 @foo(i32 %t3, i32* %t1) nounwind { + %t9 = getelementptr i32* %t1, i32 %t3 ; [#uses=1] + %t15 = load i32* %t9 ; [#uses=1] + ret i32 %t15 +} +define i32 @bar(i64 %t3, i32* %t1) nounwind { + %t9 = getelementptr i32* %t1, i64 %t3 ; [#uses=1] + %t15 = load i32* %t9 ; [#uses=1] + ret i32 %t15 +} -- 2.34.1