r201232 - ARM NEON: fix range checking on immediates.

Tim Northover tnorthover at apple.com
Wed Feb 12 04:04:59 PST 2014


Author: tnorthover
Date: Wed Feb 12 06:04:59 2014
New Revision: 201232

URL: http://llvm.org/viewvc/llvm-project?rev=201232&view=rev
Log:
ARM NEON: fix range checking on immediates.

Previously, range checking on the __builtin_neon_XYZ_v Clang intrinsics didn't
take account of the type actually passed to the call, which meant a request
like "vext_s16(a, b, 7)" was allowed through (TableGen was conservative and
allowed 0-7 for all types). This caused an assert in the backend because the
lane doesn't make sense.

Modified:
    cfe/trunk/include/clang/Basic/arm_neon.td
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/utils/TableGen/NeonEmitter.cpp

Modified: cfe/trunk/include/clang/Basic/arm_neon.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/arm_neon.td?rev=201232&r1=201231&r2=201232&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/arm_neon.td (original)
+++ cfe/trunk/include/clang/Basic/arm_neon.td Wed Feb 12 06:04:59 2014
@@ -148,6 +148,10 @@ class Inst <string n, string p, string t
   bit isVCVT_N = 0;
   bit isA64 = 0;
   bit isCrypto = 0;
+  // For immediate checks: the immediate will be assumed to specify the lane of
+  // a Q register. Only used for intrinsics which end up calling polymorphic
+  // builtins.
+  bit isLaneQ = 0;
 
   // Certain intrinsics have different names than their representative
   // instructions. This field allows us to handle this correctly when we
@@ -909,7 +913,9 @@ def VMLS_LANEQ   : IOpInst<"vmls_laneq",
                            "siUsUifQsQiQUsQUiQf", OP_MLS_LN>;
 
 def VFMA_LANE    : IInst<"vfma_lane", "dddgi", "fdQfQd">;
-def VFMA_LANEQ   : IInst<"vfma_laneq", "dddji", "fdQfQd">;
+def VFMA_LANEQ   : IInst<"vfma_laneq", "dddji", "fdQfQd"> {
+  let isLaneQ = 1;
+}
 def VFMS_LANE    : IOpInst<"vfms_lane", "dddgi", "fdQfQd", OP_FMS_LN>;
 def VFMS_LANEQ   : IOpInst<"vfms_laneq", "dddji", "fdQfQd", OP_FMS_LNQ>;
 
@@ -1302,7 +1308,9 @@ def SCALAR_VMUL_N : IInst<"vmul_n", "dds
 def SCALAR_VMUL_LANE : IInst<"vmul_lane", "ddgi", "d">;
 
 // VMUL_LANEQ d type implemented using scalar mul lane
-def SCALAR_VMUL_LANEQ   : IInst<"vmul_laneq", "ddji", "d">;
+def SCALAR_VMUL_LANEQ   : IInst<"vmul_laneq", "ddji", "d"> {
+  let isLaneQ = 1;
+}
 
 // VMULX_LANE d type implemented using scalar vmulx_lane
 def SCALAR_VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "d", OP_SCALAR_VMULX_LN>;

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=201232&r1=201231&r2=201232&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Feb 12 06:04:59 2014
@@ -326,9 +326,9 @@ Sema::CheckBuiltinFunctionCall(unsigned
 }
 
 // Get the valid immediate range for the specified NEON type code.
-static unsigned RFT(unsigned t, bool shift = false) {
+static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) {
   NeonTypeFlags Type(t);
-  int IsQuad = Type.isQuad();
+  int IsQuad = ForceQuad ? true : Type.isQuad();
   switch (Type.getEltType()) {
   case NeonTypeFlags::Int8:
   case NeonTypeFlags::Poly8:

Modified: cfe/trunk/utils/TableGen/NeonEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/NeonEmitter.cpp?rev=201232&r1=201231&r2=201232&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/NeonEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/NeonEmitter.cpp Wed Feb 12 06:04:59 2014
@@ -3007,6 +3007,14 @@ NeonEmitter::genIntrinsicRangeCheckCode(
           rangestr = "l = 1; ";
 
         rangestr += "u = RFT(TV" + shiftstr + ")";
+      } else if (ck == ClassB) {
+        // ClassB intrinsics have a type (and hence lane number) that is only
+        // known at runtime.
+        assert(immPos > 0 && "unexpected immediate operand");
+        if (R->getValueAsBit("isLaneQ"))
+          rangestr = "u = RFT(TV, false, true)";
+        else
+          rangestr = "u = RFT(TV, false, false)";
       } else {
         // The immediate generally refers to a lane in the preceding argument.
         assert(immPos > 0 && "unexpected immediate operand");





More information about the cfe-commits mailing list