[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