Add 3dNOW intrinsic header to x86intrin.h, conditioned on __3dNOW__ to
match the behavior of GCC. Also add a test for these intrinsics, which
apparently have *zero* tests. =[ Not surprisingly, Clang crashed when
compiling these.
Fix the bug in CodeGen where we failed to bitcast the argument type to
x86mmx prior to calling the LLVM intrinsic. This fixes an assert on the
new 3dnow-builtins.c test.
This is one issue impacting the efforts to get Clang to emulate the
Microsoft intrinsics headers -- 3dnow intrinsics are implictitly made
available there.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150948 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 038631e..ff25609 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -2240,6 +2240,8 @@
ID = Intrinsic::x86_3dnowa_pswapd;
break;
}
+ llvm::Type *MMXTy = llvm::Type::getX86_MMXTy(getLLVMContext());
+ Ops[0] = Builder.CreateBitCast(Ops[0], MMXTy, "cast");
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, name);
}
diff --git a/lib/Headers/x86intrin.h b/lib/Headers/x86intrin.h
index 5f9bea7..f5e4d88 100644
--- a/lib/Headers/x86intrin.h
+++ b/lib/Headers/x86intrin.h
@@ -26,6 +26,10 @@
#include <immintrin.h>
+#ifdef __3dNOW__
+#include <mm3dnow.h>
+#endif
+
#ifdef __BMI__
#include <bmiintrin.h>
#endif
@@ -46,6 +50,6 @@
#include <fma4intrin.h>
#endif
-// FIXME: SSE4A, 3dNOW, XOP, LWP, ABM
+// FIXME: SSE4A, XOP, LWP, ABM
#endif /* __X86INTRIN_H */
diff --git a/test/CodeGen/3dnow-builtins.c b/test/CodeGen/3dnow-builtins.c
new file mode 100644
index 0000000..294fbc0
--- /dev/null
+++ b/test/CodeGen/3dnow-builtins.c
@@ -0,0 +1,156 @@
+// RUN: %clang_cc1 %s -O3 -triple=x86_64-unknown-unknown -target-feature +3dnow -emit-llvm -o - | FileCheck %s
+
+// Don't include mm_malloc.h, it's system specific.
+#define __MM_MALLOC_H
+
+#include <x86intrin.h>
+
+__m64 test_m_pavgusb(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pavgusb
+ // CHECK: @llvm.x86.3dnow.pavgusb
+ return _m_pavgusb(m1, m2);
+}
+
+__m64 test_m_pf2id(__m64 m) {
+ // CHECK: define i64 @test_m_pf2id
+ // CHECK: @llvm.x86.3dnow.pf2id
+ return _m_pf2id(m);
+}
+
+__m64 test_m_pfacc(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfacc
+ // CHECK: @llvm.x86.3dnow.pfacc
+ return _m_pfacc(m1, m2);
+}
+
+__m64 test_m_pfadd(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfadd
+ // CHECK: @llvm.x86.3dnow.pfadd
+ return _m_pfadd(m1, m2);
+}
+
+__m64 test_m_pfcmpeq(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfcmpeq
+ // CHECK: @llvm.x86.3dnow.pfcmpeq
+ return _m_pfcmpeq(m1, m2);
+}
+
+__m64 test_m_pfcmpge(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfcmpge
+ // CHECK: @llvm.x86.3dnow.pfcmpge
+ return _m_pfcmpge(m1, m2);
+}
+
+__m64 test_m_pfcmpgt(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfcmpgt
+ // CHECK: @llvm.x86.3dnow.pfcmpgt
+ return _m_pfcmpgt(m1, m2);
+}
+
+__m64 test_m_pfmax(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfmax
+ // CHECK: @llvm.x86.3dnow.pfmax
+ return _m_pfmax(m1, m2);
+}
+
+__m64 test_m_pfmin(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfmin
+ // CHECK: @llvm.x86.3dnow.pfmin
+ return _m_pfmin(m1, m2);
+}
+
+__m64 test_m_pfmul(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfmul
+ // CHECK: @llvm.x86.3dnow.pfmul
+ return _m_pfmul(m1, m2);
+}
+
+__m64 test_m_pfrcp(__m64 m) {
+ // CHECK: define i64 @test_m_pfrcp
+ // CHECK: @llvm.x86.3dnow.pfrcp
+ return _m_pfrcp(m);
+}
+
+__m64 test_m_pfrcpit1(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfrcpit1
+ // CHECK: @llvm.x86.3dnow.pfrcpit1
+ return _m_pfrcpit1(m1, m2);
+}
+
+__m64 test_m_pfrcpit2(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfrcpit2
+ // CHECK: @llvm.x86.3dnow.pfrcpit2
+ return _m_pfrcpit2(m1, m2);
+}
+
+__m64 test_m_pfrsqrt(__m64 m) {
+ // CHECK: define i64 @test_m_pfrsqrt
+ // CHECK: @llvm.x86.3dnow.pfrsqrt
+ return _m_pfrsqrt(m);
+}
+
+__m64 test_m_pfrsqrtit1(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfrsqrtit1
+ // CHECK: @llvm.x86.3dnow.pfrsqit1
+ return _m_pfrsqrtit1(m1, m2);
+}
+
+__m64 test_m_pfsub(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfsub
+ // CHECK: @llvm.x86.3dnow.pfsub
+ return _m_pfsub(m1, m2);
+}
+
+__m64 test_m_pfsubr(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfsubr
+ // CHECK: @llvm.x86.3dnow.pfsubr
+ return _m_pfsubr(m1, m2);
+}
+
+__m64 test_m_pi2fd(__m64 m) {
+ // CHECK: define i64 @test_m_pi2fd
+ // CHECK: @llvm.x86.3dnow.pi2fd
+ return _m_pi2fd(m);
+}
+
+__m64 test_m_pmulhrw(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pmulhrw
+ // CHECK: @llvm.x86.3dnow.pmulhrw
+ return _m_pmulhrw(m1, m2);
+}
+
+__m64 test_m_pf2iw(__m64 m) {
+ // CHECK: define i64 @test_m_pf2iw
+ // CHECK: @llvm.x86.3dnowa.pf2iw
+ return _m_pf2iw(m);
+}
+
+__m64 test_m_pfnacc(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfnacc
+ // CHECK: @llvm.x86.3dnowa.pfnacc
+ return _m_pfnacc(m1, m2);
+}
+
+__m64 test_m_pfpnacc(__m64 m1, __m64 m2) {
+ // CHECK: define i64 @test_m_pfpnacc
+ // CHECK: @llvm.x86.3dnowa.pfpnacc
+ return _m_pfpnacc(m1, m2);
+}
+
+__m64 test_m_pi2fw(__m64 m) {
+ // CHECK: define i64 @test_m_pi2fw
+ // CHECK: @llvm.x86.3dnowa.pi2fw
+ return _m_pi2fw(m);
+}
+
+__m64 test_m_pswapdsf(__m64 m) {
+ // CHECK: define i64 @test_m_pswapdsf
+ // CHECK: @llvm.x86.3dnowa.pswapd
+ return _m_pswapdsf(m);
+}
+
+__m64 test_m_pswapdsi(__m64 m) {
+ // CHECK: define i64 @test_m_pswapdsi
+ // CHECK: @llvm.x86.3dnowa.pswapd
+ return _m_pswapdsi(m);
+}