[PATCH] D24478: [CodeGen] Fix invalid shift in mul expansion

Paweł Bylica via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 12 15:36:48 PDT 2016


chfast created this revision.
chfast added reviewers: hfinkel, majnemer.
chfast added a subscriber: llvm-commits.
chfast set the repository for this revision to rL LLVM.

When expanding mul in type legalization make sure the type for shift amount can actually fit the value. This fixes PR30354 https://llvm.org/bugs/show_bug.cgi?id=30354.

Repository:
  rL LLVM

https://reviews.llvm.org/D24478

Files:
  lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
  test/CodeGen/X86/mul-bigint.ll

Index: test/CodeGen/X86/mul-bigint.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/mul-bigint.ll
@@ -0,0 +1,50 @@
+; RUN: llc < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @test_512p(i512* %a, i512* %b, i512* %out) #0 {
+  %av = load i512, i512* %a
+  %bv = load i512, i512* %b
+  %r = mul i512 %av, %bv
+  store i512 %r, i512* %out
+  ret void
+}
+
+; CHECK-LABEL: @test_512p
+; There is a lot of inter-register motion, and so matching the instruction
+; sequence will be fragile. There should be 6 underlying multiplications.
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK: imulq
+; CHECK-NOT: imulq
+; CHECK: retq
+
+define void @test_1024p(i1024* %a, i1024* %b, i1024* %out) #0 {
+  %av = load i1024, i1024* %a
+  %bv = load i1024, i1024* %b
+  %r = mul i1024 %av, %bv
+  store i1024 %r, i1024* %out
+  ret void
+}
+
+; CHECK-LABEL: @test_1024p
+; CHECK: imulq
+; CHECK: mulq
+; CHECK: retq
+
+attributes #0 = { norecurse nounwind uwtable "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" }
Index: lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2195,18 +2195,23 @@
     // options. This is a trivially-generalized version of the code from
     // Hacker's Delight (itself derived from Knuth's Algorithm M from section
     // 4.3.1).
-    SDValue Mask =
-      DAG.getConstant(APInt::getLowBitsSet(NVT.getSizeInBits(),
-                                           NVT.getSizeInBits() >> 1), dl, NVT);
+    unsigned Bits = NVT.getSizeInBits();
+    unsigned HalfBits = Bits >> 1;
+    SDValue Mask = DAG.getConstant(APInt::getLowBitsSet(Bits, HalfBits), dl,
+                                   NVT);
     SDValue LLL = DAG.getNode(ISD::AND, dl, NVT, LL, Mask);
     SDValue RLL = DAG.getNode(ISD::AND, dl, NVT, RL, Mask);
 
     SDValue T = DAG.getNode(ISD::MUL, dl, NVT, LLL, RLL);
     SDValue TL = DAG.getNode(ISD::AND, dl, NVT, T, Mask);
 
-    SDValue Shift =
-      DAG.getConstant(NVT.getSizeInBits() >> 1, dl,
-                      TLI.getShiftAmountTy(NVT, DAG.getDataLayout()));
+    EVT ShiftAmtTy = TLI.getShiftAmountTy(NVT, DAG.getDataLayout());
+    if (APInt::getMaxValue(ShiftAmtTy.getSizeInBits()).ult(HalfBits)) {
+      // The type from TLI is too small to fit the shift amount we want.
+      // Override it with i32. The shift will have to be legalized.
+      ShiftAmtTy = MVT::i32;
+    }
+    SDValue Shift = DAG.getConstant(HalfBits, dl, ShiftAmtTy);
     SDValue TH = DAG.getNode(ISD::SRL, dl, NVT, T, Shift);
     SDValue LLH = DAG.getNode(ISD::SRL, dl, NVT, LL, Shift);
     SDValue RLH = DAG.getNode(ISD::SRL, dl, NVT, RL, Shift);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D24478.71064.patch
Type: text/x-patch
Size: 3151 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160912/f3464ce5/attachment.bin>


More information about the llvm-commits mailing list