From 4543ff09a2ebece3ef95f94182b9a8dc750998ae Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 28 Jan 2016 18:20:05 +0000 Subject: [PATCH] [X86] Don't transform X << 1 to X + X during type legalization While legalizing a 64-bit shift left by 1, the following occurs: We split the shift operand in half: a high half and a low half. We then create an ADDC with the low half and a ADDE with the high half + the carry bit from the ADDC. This is problematic if X is any_ext'd because the high half computation is now undef + undef + carry bit and there is no way to ensure that the two undef values had the same bitwise representation. This results in the lowest bit in the high half turning into garbage. Instead, do not try to turn shifts into arithmetic during type legalization. This fixes PR26350. llvm-svn: 259065 --- .../SelectionDAG/LegalizeIntegerTypes.cpp | 9 -------- llvm/test/CodeGen/X86/fold-tied-op.ll | 5 +---- llvm/test/CodeGen/X86/pr26350.ll | 21 +++++++++++++++++++ 3 files changed, 22 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/X86/pr26350.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 74f80db6d01b..abbfb1fdc1a6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1442,15 +1442,6 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, const APInt &Amt, } else if (Amt == NVTBits) { Lo = DAG.getConstant(0, DL, NVT); Hi = InL; - } else if (Amt == 1 && - TLI.isOperationLegalOrCustom(ISD::ADDC, - TLI.getTypeToExpandTo(*DAG.getContext(), NVT))) { - // Emit this X << 1 as X+X. - SDVTList VTList = DAG.getVTList(NVT, MVT::Glue); - SDValue LoOps[2] = { InL, InL }; - Lo = DAG.getNode(ISD::ADDC, DL, VTList, LoOps); - SDValue HiOps[3] = { InH, InH, Lo.getValue(1) }; - Hi = DAG.getNode(ISD::ADDE, DL, VTList, HiOps); } else { Lo = DAG.getNode(ISD::SHL, DL, NVT, InL, DAG.getConstant(Amt, DL, ShTy)); Hi = DAG.getNode(ISD::OR, DL, NVT, diff --git a/llvm/test/CodeGen/X86/fold-tied-op.ll b/llvm/test/CodeGen/X86/fold-tied-op.ll index 62fed4219387..ac6ac5249150 100644 --- a/llvm/test/CodeGen/X86/fold-tied-op.ll +++ b/llvm/test/CodeGen/X86/fold-tied-op.ll @@ -6,10 +6,7 @@ target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" target triple = "i386--netbsd" ; CHECK-LABEL: fn1 -; CHECK: shldl {{.*#+}} 4-byte Folded Spill -; CHECK: orl {{.*#+}} 4-byte Folded Reload -; CHECK: shldl {{.*#+}} 4-byte Folded Spill -; CHECK: orl {{.*#+}} 4-byte Folded Reload +; CHECK addl {{.*#+}} 4-byte Folded Reload ; CHECK: addl {{.*#+}} 4-byte Folded Reload ; CHECK: imull {{.*#+}} 4-byte Folded Reload ; CHECK: orl {{.*#+}} 4-byte Folded Reload diff --git a/llvm/test/CodeGen/X86/pr26350.ll b/llvm/test/CodeGen/X86/pr26350.ll new file mode 100644 index 000000000000..6e87cb3e8b7a --- /dev/null +++ b/llvm/test/CodeGen/X86/pr26350.ll @@ -0,0 +1,21 @@ +; RUN: llc -disable-constant-hoisting < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" +target triple = "i386-unknown-linux-gnu" + +@d = global i32 8, align 4 + +define i32 @main() { +entry: + %load = load i32, i32* @d, align 4 + %conv1 = zext i32 %load to i64 + %shl = shl i64 %conv1, 1 + %mul = and i64 %shl, 4294967312 + %cmp = icmp ugt i64 4294967295, %mul + %zext = zext i1 %cmp to i32 + ret i32 %zext +} +; CHECK: main: +; CHECK: movl d, %[[load:.*]] +; CHECK: movl %[[load]], %[[copy:.*]] +; CHECK: shrl $31, %[[copy]] +; CHECK: addl %[[load]], %[[load]]