rs created this revision.
rs added reviewers: t.p.northover, rengolin.
rs added a subscriber: cfe-commits.

Patch adds support for the intrinsics mrrc/mrrc2 and updates the existing 
mcrr/mcrr2 intrinsic definition to accept a single uint64 type as the input 
value instead of 2 uint32's as I think this makes the definition more compact.

http://reviews.llvm.org/D21179

Files:
  include/clang/Basic/BuiltinsARM.def
  lib/CodeGen/CGBuiltin.cpp
  test/CodeGen/builtins-arm.c
  test/Sema/builtins-arm.c

Index: test/Sema/builtins-arm.c
===================================================================
--- test/Sema/builtins-arm.c
+++ test/Sema/builtins-arm.c
@@ -116,11 +116,23 @@
   __builtin_arm_mcr2(15, 0, b, 13, a, 3); // expected-error {{argument to '__builtin_arm_mcr2' must be a constant integer}}
   __builtin_arm_mcr2(15, 0, b, 13, 0, a); // expected-error {{argument to '__builtin_arm_mcr2' must be a constant integer}}
 
-  __builtin_arm_mcrr( a, 0, b, c, 0); // expected-error {{argument to '__builtin_arm_mcrr' must be a constant integer}}
-  __builtin_arm_mcrr(15, a, b, c, 0); // expected-error {{argument to '__builtin_arm_mcrr' must be a constant integer}}
-  __builtin_arm_mcrr(15, 0, b, c, a); // expected-error {{argument to '__builtin_arm_mcrr' must be a constant integer}}
-
-  __builtin_arm_mcrr2( a, 0, b, c, 0); // expected-error {{argument to '__builtin_arm_mcrr2' must be a constant integer}}
-  __builtin_arm_mcrr2(15, a, b, c, 0); // expected-error {{argument to '__builtin_arm_mcrr2' must be a constant integer}}
-  __builtin_arm_mcrr2(15, 0, b, c, a); // expected-error {{argument to '__builtin_arm_mcrr2' must be a constant integer}}
+  __builtin_arm_mcrr(15, 0, b, 0);
+  __builtin_arm_mcrr( a, 0, b, 0); // expected-error {{argument to '__builtin_arm_mcrr' must be a constant integer}}
+  __builtin_arm_mcrr(15, a, b, 0); // expected-error {{argument to '__builtin_arm_mcrr' must be a constant integer}}
+  __builtin_arm_mcrr(15, 0, b, a); // expected-error {{argument to '__builtin_arm_mcrr' must be a constant integer}}
+
+  __builtin_arm_mcrr2(15, 0, b, 0);
+  __builtin_arm_mcrr2( a, 0, b, 0); // expected-error {{argument to '__builtin_arm_mcrr2' must be a constant integer}}
+  __builtin_arm_mcrr2(15, a, b, 0); // expected-error {{argument to '__builtin_arm_mcrr2' must be a constant integer}}
+  __builtin_arm_mcrr2(15, 0, b, a); // expected-error {{argument to '__builtin_arm_mcrr2' must be a constant integer}}
+
+  __builtin_arm_mrrc(15, 0, 0);
+  __builtin_arm_mrrc( a, 0, 0); // expected-error {{argument to '__builtin_arm_mrrc' must be a constant integer}}
+  __builtin_arm_mrrc(15, a, 0); // expected-error {{argument to '__builtin_arm_mrrc' must be a constant integer}}
+  __builtin_arm_mrrc(15, 0, a); // expected-error {{argument to '__builtin_arm_mrrc' must be a constant integer}}
+
+  __builtin_arm_mrrc2(15, 0, 0);
+  __builtin_arm_mrrc2( a, 0, 0); // expected-error {{argument to '__builtin_arm_mrrc2' must be a constant integer}}
+  __builtin_arm_mrrc2(15, a, 0); // expected-error {{argument to '__builtin_arm_mrrc2' must be a constant integer}}
+  __builtin_arm_mrrc2(15, 0, a); // expected-error {{argument to '__builtin_arm_mrrc2' must be a constant integer}}
 }
Index: test/CodeGen/builtins-arm.c
===================================================================
--- test/CodeGen/builtins-arm.c
+++ test/CodeGen/builtins-arm.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -Wall -Werror -triple thumbv7-eabi -target-cpu cortex-a8 -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
 
+#include <stdint.h>
+
 void *f0()
 {
   return __builtin_thread_pointer();
@@ -180,16 +182,28 @@
   __builtin_arm_mcr2(15, 0, a, 13, 0, 3);
 }
 
-void mcrr(unsigned a, unsigned b) {
-  // CHECK: define void @mcrr(i32 [[A:%.*]], i32 [[B:%.*]])
-  // CHECK: call void @llvm.arm.mcrr(i32 15, i32 0, i32 [[A]], i32 [[B]], i32 0)
-  __builtin_arm_mcrr(15, 0, a, b, 0);
+void mcrr(uint64_t a) {
+  // CHECK: define void @mcrr(i64 %{{.*}})
+  // CHECK: call void @llvm.arm.mcrr(i32 15, i32 0, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 0)
+  __builtin_arm_mcrr(15, 0, a, 0);
+}
+
+void mcrr2(uint64_t a) {
+  // CHECK: define void @mcrr2(i64 %{{.*}})
+  // CHECK: call void @llvm.arm.mcrr2(i32 15, i32 0, i32 %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 0)
+  __builtin_arm_mcrr2(15, 0, a, 0);
+}
+
+uint64_t mrrc() {
+  // CHECK: define i64 @mrrc()
+  // CHECK: call { i32, i32 } @llvm.arm.mrrc(i32 15, i32 0, i32 0)
+  return __builtin_arm_mrrc(15, 0, 0);
 }
 
-void mcrr2(unsigned a, unsigned b) {
-  // CHECK: define void @mcrr2(i32 [[A:%.*]], i32 [[B:%.*]])
-  // CHECK: call void @llvm.arm.mcrr2(i32 15, i32 0, i32 [[A]], i32 [[B]], i32 0)
-  __builtin_arm_mcrr2(15, 0, a, b, 0);
+uint64_t mrrc2() {
+  // CHECK: define i64 @mrrc2()
+  // CHECK: call { i32, i32 } @llvm.arm.mrrc2(i32 15, i32 0, i32 0)
+  return __builtin_arm_mrrc2(15, 0, 0);
 }
 
 unsigned rsr() {
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -3793,6 +3793,74 @@
     return EmitNounwindRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Ops);
   }
 
+  if (BuiltinID == ARM::BI__builtin_arm_mcrr ||
+      BuiltinID == ARM::BI__builtin_arm_mcrr2) {
+    Function *F;
+
+    switch (BuiltinID) {
+    default: llvm_unreachable("unexpected builtin");
+    case ARM::BI__builtin_arm_mcrr:
+      F = CGM.getIntrinsic(Intrinsic::arm_mcrr);
+      break;
+    case ARM::BI__builtin_arm_mcrr2:
+      F = CGM.getIntrinsic(Intrinsic::arm_mcrr2);
+      break;
+    }
+
+    // MCRR{2} instruction has 5 operands but
+    // the intrinsic has 4 because Rt and Rt2
+    // are represented as a single unsigned 64
+    // bit integer in the intrinsic definition
+    // but internally it's represented as 2 32
+    // bit integers.
+
+    Value *Arg0 = EmitScalarExpr(E->getArg(0)); /* coproc */
+    Value *Arg1 = EmitScalarExpr(E->getArg(1)); /* opc1 */
+    Value *Arg2 = EmitScalarExpr(E->getArg(2)); /* Rt and Rt2 */
+    Value *Arg3 = EmitScalarExpr(E->getArg(3)); /* CRm */
+
+    Value *C1 = llvm::ConstantInt::get(Int64Ty, 32);
+    Value *Arg2a = Builder.CreateTruncOrBitCast(Arg2, Int32Ty);
+    Value *Arg2b = Builder.CreateLShr(Arg2, C1);
+    Arg2b = Builder.CreateTruncOrBitCast(Arg2b, Int32Ty);
+
+    return Builder.CreateCall(F, {Arg0, Arg1, Arg2a, Arg2b, Arg3});
+  }
+
+  if (BuiltinID == ARM::BI__builtin_arm_mrrc ||
+      BuiltinID == ARM::BI__builtin_arm_mrrc2) {
+    Function *F;
+
+    switch (BuiltinID) {
+    default: llvm_unreachable("unexpected builtin");
+    case ARM::BI__builtin_arm_mrrc:
+      F = CGM.getIntrinsic(Intrinsic::arm_mrrc);
+      break;
+    case ARM::BI__builtin_arm_mrrc2:
+      F = CGM.getIntrinsic(Intrinsic::arm_mrrc2);
+      break;
+    }
+
+    Value *Arg0 = EmitScalarExpr(E->getArg(0)); /* coproc */
+    Value *Arg1 = EmitScalarExpr(E->getArg(1)); /* opc */
+    Value *Arg2 = EmitScalarExpr(E->getArg(2)); /* CRm */
+    Value *Val = Builder.CreateCall(F, {Arg0, Arg1, Arg2});
+
+    // Returns an unsigned 64 bit integer, represented
+    // as two 32 bit integers.
+
+    Value *Val0 = Builder.CreateExtractValue(Val, 1);
+    Value *Val1 = Builder.CreateExtractValue(Val, 0);
+    Val0 = Builder.CreateZExt(Val0, Int64Ty);
+    Val1 = Builder.CreateZExt(Val1, Int64Ty);
+
+    Value *ShiftCast = llvm::ConstantInt::get(Int64Ty, 32);
+    Val = Builder.CreateShl(Val0, ShiftCast, "shl", true);
+    Val = Builder.CreateOr(Val, Val1);
+
+    return Builder.CreateBitCast(Val, ConvertType(E->getType()));
+  }
+
   if (BuiltinID == ARM::BI__builtin_arm_ldrexd ||
       ((BuiltinID == ARM::BI__builtin_arm_ldrex ||
         BuiltinID == ARM::BI__builtin_arm_ldaex) &&
Index: include/clang/Basic/BuiltinsARM.def
===================================================================
--- include/clang/Basic/BuiltinsARM.def
+++ include/clang/Basic/BuiltinsARM.def
@@ -58,14 +58,16 @@
 BUILTIN(__builtin_arm_stc2, "vUIiUIiv*", "")
 BUILTIN(__builtin_arm_stc2l, "vUIiUIiv*", "")
 
+BUILTIN(__builtin_arm_cdp, "vUIiUIiUIiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_cdp2, "vUIiUIiUIiUIiUIiUIi", "")
 BUILTIN(__builtin_arm_mcr, "vUIiUIiUiUIiUIiUIi", "")
 BUILTIN(__builtin_arm_mcr2, "vUIiUIiUiUIiUIiUIi", "")
 BUILTIN(__builtin_arm_mrc, "UiUIiUIiUIiUIiUIi", "")
 BUILTIN(__builtin_arm_mrc2, "UiUIiUIiUIiUIiUIi", "")
-BUILTIN(__builtin_arm_cdp, "vUIiUIiUIiUIiUIiUIi", "")
-BUILTIN(__builtin_arm_cdp2, "vUIiUIiUIiUIiUIiUIi", "")
-BUILTIN(__builtin_arm_mcrr, "vUIiUIiUiUiUIi", "")
-BUILTIN(__builtin_arm_mcrr2, "vUIiUIiUiUiUIi", "")
+BUILTIN(__builtin_arm_mcrr, "vUIiUIiLLUiUIi", "")
+BUILTIN(__builtin_arm_mcrr2, "vUIiUIiLLUiUIi", "")
+BUILTIN(__builtin_arm_mrrc, "LLUiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mrrc2, "LLUiUIiUIiUIi", "")
 
 // CRC32
 BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to