From 4106876da9a8b6e50457f871acc3ace2542b19a5 Mon Sep 17 00:00:00 2001 From: Andrey Turetskiy Date: Tue, 16 Feb 2016 12:47:45 +0000 Subject: [PATCH] [X86] PR26575: Fix LEA optimization pass. Add a missing check for a type of address displacement operand of the load/store instruction being a candidate for LEA substitution. Ref: https://llvm.org/bugs/show_bug.cgi?id=26575 Differential Revision: http://reviews.llvm.org/D17261 llvm-svn: 260959 --- lib/Target/X86/X86OptimizeLEAs.cpp | 5 ++++ test/CodeGen/X86/lea-opt-memop-check.ll | 32 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 test/CodeGen/X86/lea-opt-memop-check.ll diff --git a/lib/Target/X86/X86OptimizeLEAs.cpp b/lib/Target/X86/X86OptimizeLEAs.cpp index 9f7de9a8c6a..def49dfbe5c 100644 --- a/lib/Target/X86/X86OptimizeLEAs.cpp +++ b/lib/Target/X86/X86OptimizeLEAs.cpp @@ -434,6 +434,11 @@ bool OptimizeLEAPass::removeRedundantAddrCalc(MemOpMap &LEAs) { MemOpNo += X86II::getOperandBias(Desc); + // Address displacement must be an immediate or a global. + MachineOperand &Disp = MI.getOperand(MemOpNo + X86::AddrDisp); + if (!Disp.isImm() && !Disp.isGlobal()) + continue; + // Get the best LEA instruction to replace address calculation. MachineInstr *DefMI; int64_t AddrDispShift; diff --git a/test/CodeGen/X86/lea-opt-memop-check.ll b/test/CodeGen/X86/lea-opt-memop-check.ll new file mode 100644 index 00000000000..1da97997754 --- /dev/null +++ b/test/CodeGen/X86/lea-opt-memop-check.ll @@ -0,0 +1,32 @@ +; REQUIRES: asserts +; RUN: llc < %s -march=x86 -mtriple=i686-pc-win32 -enable-x86-lea-opt | FileCheck %s + +; PR26575 +; Assertion `(Disp->isImm() || Disp->isGlobal()) && (Other.Disp->isImm() || Other.Disp->isGlobal()) && "Address displacement operand is always an immediate or a global"' failed. + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc" + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) argmemonly nounwind +declare <2 x i64> @_mm_xor_si128(<2 x i64>, <2 x i64>) optsize +declare <2 x i64> @llvm.x86.pclmulqdq(<2 x i64>, <2 x i64>, i8) nounwind readnone +declare <4 x float> @_mm_castsi128_ps(<2 x i64>) optsize + +define void @test(i8* nocapture readonly %src, i32 %len) #0 { + %parts = alloca [4 x i32], align 4 + %part0 = bitcast [4 x i32]* %parts to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %part0, i8* %src, i32 %len, i32 1, i1 false) + %call0 = tail call <2 x i64> @_mm_xor_si128(<2 x i64> undef, <2 x i64> ) + %tmp0 = tail call <2 x i64> @llvm.x86.pclmulqdq(<2 x i64> undef, <2 x i64> , i8 16) + %call1 = tail call <4 x float> @_mm_castsi128_ps(<2 x i64> %tmp0) + ret void +; CHECK-LABEL: test: +; CHECK: leal{{.*}} +; CHECK: calll _memcpy +; CHECK: movaps __xmm@{{[0-9a-f]+}}, %xmm1 +; CHECK: calll __mm_xor_si128 +; CHECK: pclmulqdq $16, __xmm@{{[0-9a-f]+}}, %xmm0 +; CHECK: jmp __mm_castsi128_ps +} + +attributes #0 = { nounwind optsize "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-features"="+mmx,+pclmul,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }