Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -3456,8 +3456,13 @@ SDValue IdxN = getValue(Idx); // If the index is smaller or larger than intptr_t, truncate or extend - // it. - IdxN = DAG.getSExtOrTrunc(IdxN, getCurSDLoc(), N.getValueType()); + // it. Prefer a zext vs a sext if we can. + bool KnownZero, KnownOne; + ComputeSignBit(const_cast(Idx), KnownZero, KnownOne, DL); + if (KnownZero) + IdxN = DAG.getZExtOrTrunc(IdxN, getCurSDLoc(), N.getValueType()); + else + IdxN = DAG.getSExtOrTrunc(IdxN, getCurSDLoc(), N.getValueType()); // If this is a multiply by a power of two, turn it into a shl // immediately. This is a very common case. Index: test/CodeGen/X86/gep-sext.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/gep-sext.ll @@ -0,0 +1,49 @@ +; RUN: llc < %s 2>&1 | FileCheck %s + +target datalayout = "e-p:32:32" +target triple = "x86_64-linux-unknown" + + +declare void @use(i32) + +; Sign extension is manditory for the gep argument +define void @test(i32* %p, i32 %index) { +; CHECK-LABEL: test: +; CHECK: movslq %esi, %rax +; CHECK: movl (%rdi,%rax,4), %edi + %addr = getelementptr i32* %p, i32 %index + %val = load i32* %addr + call void @use(i32 %val) + ret void +} + +; Zero extension is manditory since the high bits of %esi +; aren't specified +define void @test2(i32* %p, i32 %index) { +; CHECK-LABEL: test2 +; CHECK: movl %esi, %eax +; CHECK: movl (%rdi,%rax,4), %edi + %i = zext i32 %index to i64 + %addr = getelementptr i32* %p, i64 %i + %val = load i32* %addr + call void @use(i32 %val) + ret void +} +define void @test3(i32* %p, i32 %index) { +; CHECK-LABEL: test3 +; CHECK-NOT: movslq +; CHECK: movl 352(%rdi), %eax +; CHECK: movl 160(%rdi,%rax,4), %edi + %addr_begin = getelementptr i32* %p, i64 40 + %addr_fixed = getelementptr i32* %addr_begin, i64 48 + %val_fixed = load i32* %addr_fixed, !range !0 + %addr = getelementptr i32* %addr_begin, i32 %val_fixed + %val = load i32* %addr + call void @use(i32 %val) + ret void +} +;; !range !0 +!0 = !{i32 0, i32 2147483647} + + +