Patches 1 and 2 fix a bug (that has been present in 3.7 and 3.8) where it can use the wrong instruction in some cases (libav with inline assembly disabled), causing rounding errors in integer audio dct's there. Patch 3 allows building inline assembly with clang/llvm in MSVC mode.
134 lines
5.1 KiB
Diff
134 lines
5.1 KiB
Diff
From 9ce71bff387ce9e30adddf72a29874bbb058dd5a Mon Sep 17 00:00:00 2001
|
|
From: Sam Parker <sam.parker@arm.com>
|
|
Date: Mon, 25 Jul 2016 09:20:20 +0000
|
|
Subject: [PATCH 2/3] [ARM] Enable ISel of SMMLS for ARM and Thumb2
|
|
|
|
Use ISelDAGToDAG to recognise the SMMLS instruction pattern.
|
|
|
|
Differential Revision: https://reviews.llvm.org/D22562
|
|
|
|
Cherry-picked from SVN trunk commit 276624, git mirror commit
|
|
161eae5670.
|
|
---
|
|
lib/Target/ARM/ARMISelDAGToDAG.cpp | 30 ++++++++++++++++++++++++++++++
|
|
lib/Target/ARM/ARMInstrThumb2.td | 9 ++++-----
|
|
test/CodeGen/ARM/smml.ll | 36 ++++++++++++++++++++++++++++++++++--
|
|
3 files changed, 68 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
|
|
index 20db3d3..96cb691 100644
|
|
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
|
|
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
|
|
@@ -3037,6 +3037,36 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
|
|
return;
|
|
}
|
|
}
|
|
+ case ARMISD::SUBE: {
|
|
+ if (!Subtarget->hasV6Ops())
|
|
+ break;
|
|
+ // Look for a pattern to match SMMLS
|
|
+ // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b))))
|
|
+ if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI ||
|
|
+ N->getOperand(2).getOpcode() != ARMISD::SUBC)
|
|
+ break;
|
|
+
|
|
+ if (Subtarget->isThumb())
|
|
+ assert(Subtarget->hasThumb2() &&
|
|
+ "This pattern should not be generated for Thumb");
|
|
+
|
|
+ SDValue SmulLoHi = N->getOperand(1);
|
|
+ SDValue Subc = N->getOperand(2);
|
|
+ auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0));
|
|
+
|
|
+ if (!Zero || Zero->getZExtValue() != 0 ||
|
|
+ Subc.getOperand(1) != SmulLoHi.getValue(0) ||
|
|
+ N->getOperand(1) != SmulLoHi.getValue(1) ||
|
|
+ N->getOperand(2) != Subc.getValue(1))
|
|
+ break;
|
|
+
|
|
+ unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS;
|
|
+ SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1),
|
|
+ N->getOperand(0), getAL(CurDAG, dl),
|
|
+ CurDAG->getRegister(0, MVT::i32) };
|
|
+ ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops));
|
|
+ return;
|
|
+ }
|
|
case ISD::LOAD: {
|
|
if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
|
|
if (tryT2IndexedLoad(N))
|
|
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
|
|
index 64f5dad..599b552 100644
|
|
--- a/lib/Target/ARM/ARMInstrThumb2.td
|
|
+++ b/lib/Target/ARM/ARMInstrThumb2.td
|
|
@@ -2606,12 +2606,11 @@ class T2FourRegSMMLA<bits<3> op22_20, bits<4> op7_4, string opc,
|
|
let Inst{7-4} = op7_4;
|
|
}
|
|
|
|
-def t2SMMLA : T2FourRegSMMLA<0b101, 0b0000, "smmla",
|
|
+def t2SMMLA : T2FourRegSMMLA<0b101, 0b0000, "smmla",
|
|
[(set rGPR:$Rd, (add (mulhs rGPR:$Rm, rGPR:$Rn), rGPR:$Ra))]>;
|
|
-def t2SMMLAR: T2FourRegSMMLA<0b101, 0b0001, "smmlar", []>;
|
|
-def t2SMMLS: T2FourRegSMMLA<0b110, 0b0000, "smmls",
|
|
- [(set rGPR:$Rd, (sub rGPR:$Ra, (mulhs rGPR:$Rn, rGPR:$Rm)))]>;
|
|
-def t2SMMLSR:T2FourRegSMMLA<0b110, 0b0001, "smmlsr", []>;
|
|
+def t2SMMLAR: T2FourRegSMMLA<0b101, 0b0001, "smmlar", []>;
|
|
+def t2SMMLS: T2FourRegSMMLA<0b110, 0b0000, "smmls", []>;
|
|
+def t2SMMLSR: T2FourRegSMMLA<0b110, 0b0001, "smmlsr", []>;
|
|
|
|
class T2ThreeRegSMUL<bits<3> op22_20, bits<2> op5_4, string opc,
|
|
list<dag> pattern>
|
|
diff --git a/test/CodeGen/ARM/smml.ll b/test/CodeGen/ARM/smml.ll
|
|
index fc73eb7..807445f 100644
|
|
--- a/test/CodeGen/ARM/smml.ll
|
|
+++ b/test/CodeGen/ARM/smml.ll
|
|
@@ -1,8 +1,20 @@
|
|
-; RUN: llc -mtriple=arm-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s
|
|
+; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s -check-prefix=CHECK
|
|
+; RUN: llc -mtriple=armv6-eabi %s -o - | FileCheck %s -check-prefix=CHECK-V6
|
|
+; RUN: llc -mtriple=armv7-eabi %s -o - | FileCheck %s -check-prefix=CHECK-V7
|
|
+; RUN: llc -mtriple=thumb-eabi %s -o - | FileCheck %s -check-prefix=CHECK-THUMB
|
|
+; RUN: llc -mtriple=thumbv6-eabi %s -o - | FileCheck %s -check-prefix=CHECK-THUMB
|
|
+; RUN: llc -mtriple=thumbv6t2-eabi %s -o - | FileCheck %s -check-prefix=CHECK-THUMBV6T2
|
|
+; RUN: llc -mtriple=thumbv7-eabi %s -o - | FileCheck %s -check-prefix=CHECK-THUMBV7
|
|
|
|
-define i32 @f(i32 %a, i32 %b, i32 %c) nounwind readnone ssp {
|
|
+define i32 @Test0(i32 %a, i32 %b, i32 %c) nounwind readnone ssp {
|
|
entry:
|
|
+; CHECK-LABEL: Test0
|
|
; CHECK-NOT: smmls
|
|
+; CHECK-V6-NOT: smmls
|
|
+; CHECK-V7-NOT: smmls
|
|
+; CHECK_THUMB-NOT: smmls
|
|
+; CHECK-THUMBV6T2-NOT: smmls
|
|
+; CHECK-THUMBV7-NOT: smmls
|
|
%conv4 = zext i32 %a to i64
|
|
%conv1 = sext i32 %b to i64
|
|
%conv2 = sext i32 %c to i64
|
|
@@ -12,3 +24,23 @@ entry:
|
|
%conv3 = trunc i64 %sub to i32
|
|
ret i32 %conv3
|
|
}
|
|
+
|
|
+define i32 @Test1(i32 %a, i32 %b, i32 %c) {
|
|
+;CHECK-LABEL: Test1
|
|
+;CHECK-NOT: smmls
|
|
+;CHECK-THUMB-NOT: smmls
|
|
+;CHECK-V6: smmls r0, [[Rn:r[1-2]]], [[Rm:r[1-2]]], r0
|
|
+;CHECK-V7: smmls r0, [[Rn:r[1-2]]], [[Rm:r[1-2]]], r0
|
|
+;CHECK-THUMBV6T2: smmls r0, [[Rn:r[1-2]]], [[Rm:r[1-2]]], r0
|
|
+;CHECK-THUMBV7: smmls r0, [[Rn:r[1-2]]], [[Rm:r[1-2]]], r0
|
|
+entry:
|
|
+ %conv = sext i32 %b to i64
|
|
+ %conv1 = sext i32 %c to i64
|
|
+ %mul = mul nsw i64 %conv1, %conv
|
|
+ %conv26 = zext i32 %a to i64
|
|
+ %shl = shl nuw i64 %conv26, 32
|
|
+ %sub = sub nsw i64 %shl, %mul
|
|
+ %shr7 = lshr i64 %sub, 32
|
|
+ %conv3 = trunc i64 %shr7 to i32
|
|
+ ret i32 %conv3
|
|
+}
|
|
--
|
|
2.7.4
|
|
|