[llvm-commits] [llvm-gcc-4.2] r99074 - in /llvm-gcc-4.2/trunk/gcc: c-typeck.c config/arm/arm.c llvm-convert.cpp llvm-internal.h target-def.h target.h

Anton Korobeynikov asl at math.spbu.ru
Sat Mar 20 12:21:43 PDT 2010


Author: asl
Date: Sat Mar 20 14:21:43 2010
New Revision: 99074

URL: http://llvm.org/viewvc/llvm-project?rev=99074&view=rev
Log:
Perform necessary promotion for valus of HF mode (half-precision floats):
 1. Promote to floats inside frontend
 2. Emit needed conversion instructions inside llvm-convert.
C frontend only.

Modified:
    llvm-gcc-4.2/trunk/gcc/c-typeck.c
    llvm-gcc-4.2/trunk/gcc/config/arm/arm.c
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-internal.h
    llvm-gcc-4.2/trunk/gcc/target-def.h
    llvm-gcc-4.2/trunk/gcc/target.h

Modified: llvm-gcc-4.2/trunk/gcc/c-typeck.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/c-typeck.c?rev=99074&r1=99073&r2=99074&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/c-typeck.c (original)
+++ llvm-gcc-4.2/trunk/gcc/c-typeck.c Sat Mar 20 14:21:43 2010
@@ -1692,7 +1692,7 @@
 tree
 default_conversion (tree exp)
 {
-  tree orig_exp;
+  tree orig_exp, promoted_exp;
   tree type = TREE_TYPE (exp);
   enum tree_code code = TREE_CODE (type);
 
@@ -1721,6 +1721,10 @@
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
+  promoted_exp = targetm.perform_target_promotions (exp);
+  if (promoted_exp != NULL_TREE)
+    return promoted_exp;
+
   if (INTEGRAL_TYPE_P (type))
     return perform_integral_promotions (exp);
 

Modified: llvm-gcc-4.2/trunk/gcc/config/arm/arm.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/arm/arm.c?rev=99074&r1=99073&r2=99074&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/arm/arm.c (original)
+++ llvm-gcc-4.2/trunk/gcc/config/arm/arm.c Sat Mar 20 14:21:43 2010
@@ -143,6 +143,8 @@
 static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
 /* APPLE LOCAL v7 support. Merge from mainline */
 static void thumb1_output_function_prologue (FILE *, HOST_WIDE_INT);
+static tree arm_perform_target_promotions(tree);
+static bool arm_is_fp16(tree);
 static int arm_comp_type_attributes (tree, tree);
 static void arm_set_default_type_attributes (tree);
 static int arm_adjust_cost (rtx, rtx, rtx, int);
@@ -513,6 +515,11 @@
 #define TARGET_MD_ASM_CLOBBERS arm_md_asm_clobbers
 /* APPLE LOCAL end 6902792 Q register clobbers in inline asm */
 
+/* LLVM LOCAL begin */
+#undef TARGET_PERFORM_TARGET_PROMOTIONS
+#define TARGET_PERFORM_TARGET_PROMOTIONS arm_perform_target_promotions
+/* LLVM LOCAL end */
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -3837,6 +3844,26 @@
   return 1;
 }
 
+/* LLVM LOCAL begin */
+bool
+arm_is_fp16(tree ty)
+{
+  return (SCALAR_FLOAT_TYPE_P (ty) && TYPE_PRECISION (ty) == 16);
+}
+
+
+tree
+arm_perform_target_promotions (tree exp)
+{
+  /* FIXME: Is NOP_EXPR better here? */
+  if (arm_is_fp16 (TREE_TYPE(exp)))
+    return build1 (CONVERT_EXPR, float_type_node, exp);
+
+  return NULL_TREE;
+}
+
+/* LLVM LOCAL end */
+
 /* APPLE LOCAL begin ARM longcall */
 /*  Encode long_call or short_call attribute by prefixing
     symbol name in DECL with a special character FLAG.  */

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=99074&r1=99073&r2=99074&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Sat Mar 20 14:21:43 2010
@@ -3197,6 +3197,29 @@
   return RHS;
 }
 
+Value *TreeToLLVM::EmitFP16Conversion(tree fromty, tree toty, Value *V) {
+  bool OpIsSigned = !TYPE_UNSIGNED(fromty);
+  bool ExpIsSigned = !TYPE_UNSIGNED(toty);
+
+  if (SCALAR_FLOAT_TYPE_P (fromty) && TYPE_PRECISION (fromty) == 16) {
+    // HF -> something cast is performed as HF -> SF -> something
+    Value *Result =
+      Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
+						   Intrinsic::convert_from_fp16),
+			 &V, &V+1);
+    return CastToAnyType(Result, false, ConvertType(toty), ExpIsSigned);
+  } else if (SCALAR_FLOAT_TYPE_P (toty) && TYPE_PRECISION (toty) == 16) {
+    // something -> HF cast is performed as something -> SF -> HF
+    V = CastToAnyType(V, OpIsSigned, Type::getFloatTy(Context), false);
+    return Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
+						Intrinsic::convert_to_fp16),
+			      &V, &V+1);
+  }
+
+  return 0;
+}
+
+
 Value *TreeToLLVM::EmitNOP_EXPR(tree exp, const MemRef *DestLoc) {
   if (TREE_CODE(TREE_TYPE(exp)) == VOID_TYPE &&    // deleted statement.
       TREE_CODE(TREE_OPERAND(exp, 0)) == INTEGER_CST)
@@ -3208,9 +3231,14 @@
   if (DestLoc == 0) {
     // Scalar to scalar copy.
     assert(!isAggregateTreeType(TREE_TYPE(Op))
-           && "Aggregate to scalar nop_expr!");
+	   && "Aggregate to scalar nop_expr!");
     Value *OpVal = Emit(Op, DestLoc);
     if (Ty->isVoidTy()) return 0;
+
+    // Special case: something <-> HF casts are made via special intrinsics.
+    if (Value *V = EmitFP16Conversion(TREE_TYPE(Op), TREE_TYPE(exp), OpVal))
+      return V;
+
     return CastToAnyType(OpVal, OpIsSigned, Ty, ExpIsSigned);
   } else if (isAggregateTreeType(TREE_TYPE(Op))) {
     // Aggregate to aggregate copy.
@@ -3231,10 +3259,16 @@
 
 Value *TreeToLLVM::EmitCONVERT_EXPR(tree exp, const MemRef *DestLoc) {
   assert(!DestLoc && "Cannot handle aggregate casts!");
-  Value *Op = Emit(TREE_OPERAND(exp, 0), 0);
-  bool OpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
-  bool ExpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
-  return CastToAnyType(Op, OpIsSigned, ConvertType(TREE_TYPE(exp)),ExpIsSigned);
+  tree op0 = TREE_OPERAND(exp, 0);
+  tree opty = TREE_TYPE(op0), expty = TREE_TYPE(exp);
+  Value *Op = Emit(op0, 0);
+
+  // Special case: something <-> HF casts are made via special intrinsics.
+  if (Value *V = EmitFP16Conversion(opty, expty, Op))
+    return V;
+
+  bool OpIsSigned = !TYPE_UNSIGNED(opty), ExpIsSigned = !TYPE_UNSIGNED(expty);
+  return CastToAnyType(Op, OpIsSigned, ConvertType(expty), ExpIsSigned);
 }
 
 Value *TreeToLLVM::EmitVIEW_CONVERT_EXPR(tree exp, const MemRef *DestLoc) {
@@ -3464,31 +3498,40 @@
 Value *TreeToLLVM::EmitCompare(tree exp, unsigned UIOpc, unsigned SIOpc,
                                unsigned FPPred, const Type *DestTy) {
   // Get the type of the operands
-  tree Op0Ty = TREE_TYPE(TREE_OPERAND(exp,0));
+  tree lhsty = TREE_TYPE(TREE_OPERAND(exp, 0));
+  tree rhsty = TREE_TYPE(TREE_OPERAND(exp, 1));
 
   Value *Result;
 
   // Deal with complex types
-  if (TREE_CODE(Op0Ty) == COMPLEX_TYPE) {
+  if (TREE_CODE(lhsty) == COMPLEX_TYPE) {
     Result = EmitComplexBinOp(exp, 0);  // Complex ==/!=
   } else {
     // Get the compare operands, in the right type. Comparison of struct is not
     // allowed, so this is safe as we already handled complex (struct) type.
     Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
     Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
-    bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
-    bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 1)));
+
+    // FIXME: This should be generalized for other storage-only types, if any.
+    if (Value *V = EmitFP16Conversion(lhsty, float_type_node, LHS)) {
+      LHS = V; lhsty = float_type_node;
+    }
+    if (Value *V = EmitFP16Conversion(rhsty, float_type_node, RHS)) {
+      RHS = V; rhsty = float_type_node;
+    }
+
+    bool LHSIsSigned = !TYPE_UNSIGNED(lhsty);
+    bool RHSIsSigned = !TYPE_UNSIGNED(rhsty);
     RHS = CastToAnyType(RHS, RHSIsSigned, LHS->getType(), LHSIsSigned);
     assert(LHS->getType() == RHS->getType() && "Binop type equality failure!");
 
-    if (FLOAT_TYPE_P(Op0Ty)) {
+    if (FLOAT_TYPE_P(lhsty)) {
       // Handle floating point comparisons, if we get here.
       Result = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS);
     } else {
       // Handle the integer/pointer cases.  Determine which predicate to use based
       // on signedness.
-      ICmpInst::Predicate pred =
-        ICmpInst::Predicate(TYPE_UNSIGNED(Op0Ty) ? UIOpc : SIOpc);
+      ICmpInst::Predicate pred = ICmpInst::Predicate(LHSIsSigned ? SIOpc: UIOpc);
 
       // Get the compare instructions
       Result = Builder.CreateICmp(pred, LHS, RHS);
@@ -3508,23 +3551,35 @@
 /// EmitBinOp - 'exp' is a binary operator.
 ///
 Value *TreeToLLVM::EmitBinOp(tree exp, const MemRef *DestLoc, unsigned Opc) {
-  const Type *Ty = ConvertType(TREE_TYPE(exp));
+  tree expty = TREE_TYPE(exp);
+  const Type *Ty = ConvertType(expty);
   if (Ty->isPointerTy())
     return EmitPtrBinOp(exp, Opc);   // Pointer arithmetic!
   if (Ty->isStructTy())
     return EmitComplexBinOp(exp, DestLoc);
   assert(Ty->isSingleValueType() && DestLoc == 0 &&
-         "Bad binary operation!");
+	 "Bad binary operation!");
+
+  tree lhsty = TREE_TYPE(TREE_OPERAND(exp, 0));
+  tree rhsty = TREE_TYPE(TREE_OPERAND(exp, 1));
 
   Value *LHS = Emit(TREE_OPERAND(exp, 0), 0);
   Value *RHS = Emit(TREE_OPERAND(exp, 1), 0);
 
+  // FIXME: This should be generalized for other storage-only types, if any.
+  if (Value *V = EmitFP16Conversion(lhsty, float_type_node, LHS)) {
+    LHS = V; lhsty = float_type_node; Ty = Type::getFloatTy(Context);
+  }
+  if (Value *V = EmitFP16Conversion(rhsty, float_type_node, RHS)) {
+    RHS = V; rhsty = float_type_node; Ty = Type::getFloatTy(Context);
+  }
+
   // GCC has no problem with things like "xor uint X, int 17", and X-Y, where
   // X and Y are pointer types, but the result is an integer.  As such, convert
   // everything to the result type.
-  bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
-  bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 1)));
-  bool TyIsSigned  = !TYPE_UNSIGNED(TREE_TYPE(exp));
+  bool LHSIsSigned = !TYPE_UNSIGNED(lhsty);
+  bool RHSIsSigned = !TYPE_UNSIGNED(rhsty);
+  bool TyIsSigned  = !TYPE_UNSIGNED(expty);
   bool IsExactDiv  = TREE_CODE(exp) == EXACT_DIV_EXPR;
 
   LHS = CastToAnyType(LHS, LHSIsSigned, Ty, TyIsSigned);
@@ -3538,7 +3593,7 @@
   if (isLogicalOp &&
       (Ty->isFloatingPointTy() ||
        (Ty->isVectorTy() &&
-        cast<VectorType>(Ty)->getElementType()->isFloatingPointTy()))) {
+	cast<VectorType>(Ty)->getElementType()->isFloatingPointTy()))) {
     Ty = getSuitableBitCastIntType(Ty);
     LHS = BitCastToType(LHS, Ty);
     RHS = BitCastToType(RHS, Ty);
@@ -3547,16 +3602,21 @@
   Value *V;
   if (Opc == Instruction::SDiv && IsExactDiv)
     V = Builder.CreateExactSDiv(LHS, RHS);
-  else if (Opc == Instruction::Add && !TYPE_OVERFLOW_WRAPS(TREE_TYPE(exp)))
+  else if (Opc == Instruction::Add && !TYPE_OVERFLOW_WRAPS(expty))
     V = Builder.CreateNSWAdd(LHS, RHS);
-  else if (Opc == Instruction::Sub && !TYPE_OVERFLOW_WRAPS(TREE_TYPE(exp)))
+  else if (Opc == Instruction::Sub && !TYPE_OVERFLOW_WRAPS(expty))
     V = Builder.CreateNSWSub(LHS, RHS);
-  else if (Opc == Instruction::Mul && !TYPE_OVERFLOW_WRAPS(TREE_TYPE(exp)))
+  else if (Opc == Instruction::Mul && !TYPE_OVERFLOW_WRAPS(expty))
     V = Builder.CreateNSWMul(LHS, RHS);
   else
     V = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
   if (ResTy != Ty)
     V = BitCastToType(V, ResTy);
+
+  // FIXME: This should be generalized for other storage-only types, if any.
+  if (Value *CV = EmitFP16Conversion(float_type_node, expty, V))
+    V = CV;
+
   return V;
 }
 

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=99074&r1=99073&r2=99074&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Sat Mar 20 14:21:43 2010
@@ -492,6 +492,7 @@
   Value *EmitCallOf(Value *Callee, tree_node *exp, const MemRef *DestLoc,
                     const AttrListPtr &PAL);
   Value *EmitMODIFY_EXPR(tree_node *exp, const MemRef *DestLoc);
+  Value *EmitFP16Conversion(tree_node *fromty, tree_node *toty, Value *V);
   Value *EmitNOP_EXPR(tree_node *exp, const MemRef *DestLoc);
   Value *EmitCONVERT_EXPR(tree_node *exp, const MemRef *DestLoc);
   Value *EmitVIEW_CONVERT_EXPR(tree_node *exp, const MemRef *DestLoc);

Modified: llvm-gcc-4.2/trunk/gcc/target-def.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/target-def.h?rev=99074&r1=99073&r2=99074&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/target-def.h (original)
+++ llvm-gcc-4.2/trunk/gcc/target-def.h Sat Mar 20 14:21:43 2010
@@ -476,6 +476,9 @@
 #define TARGET_INVALID_CONVERSION hook_constcharptr_tree_tree_null
 #define TARGET_INVALID_UNARY_OP hook_constcharptr_int_tree_null
 #define TARGET_INVALID_BINARY_OP hook_constcharptr_int_tree_tree_null
+/* LLVM LOCAL begin */
+#define TARGET_PERFORM_TARGET_PROMOTIONS hook_tree_tree_null
+/* LLVM LOCAL end */
 
 #define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false
 
@@ -739,6 +742,9 @@
   TARGET_INVALID_CONVERSION,			\
   TARGET_INVALID_UNARY_OP,			\
   TARGET_INVALID_BINARY_OP,			\
+  /* LLVM LOCAL begin */			\
+  TARGET_PERFORM_TARGET_PROMOTIONS,		\
+  /* LLVM LOCAL end   */			\
   TARGET_SECONDARY_RELOAD,			\
   TARGET_CXX,					\
   TARGET_EXTRA_LIVE_ON_ENTRY,                    \

Modified: llvm-gcc-4.2/trunk/gcc/target.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/target.h?rev=99074&r1=99073&r2=99074&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/target.h (original)
+++ llvm-gcc-4.2/trunk/gcc/target.h Sat Mar 20 14:21:43 2010
@@ -770,6 +770,10 @@
      is not permitted on TYPE1 and TYPE2, NULL otherwise.  */
   const char *(*invalid_binary_op) (int op, tree type1, tree type2);
 
+  /* LLVM LOCAL begin */
+  tree (*perform_target_promotions) (tree exp);
+  /* LLVM LOCAL end */
+
   /* Return the class for a secondary reload, and fill in extra information.  */
   enum reg_class (*secondary_reload) (bool, rtx, enum reg_class,
 				      enum machine_mode,





More information about the llvm-commits mailing list