Browse Source

[spirv] Provide literal type hint in cast function (#1034)

Ehsan 7 years ago
parent
commit
e6f6fd91a1

+ 18 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -1903,6 +1903,24 @@ SpirvEvalInfo SPIRVEmitter::doCastExpr(const CastExpr *expr) {
   const QualType subExprType = subExpr->getType();
   const QualType toType = expr->getType();
 
+  // Unfortunately the front-end fails to deduce some types in certain cases.
+  // Provide a hint about literal type usage if possible.
+  TypeTranslator::LiteralTypeHint hint(typeTranslator);
+
+  // 'literal int' to 'float' conversion. If a literal integer is to be used as
+  // a 32-bit float, the hint is a 32-bit integer.
+  if (toType->isFloatingType() &&
+      subExprType->isSpecificBuiltinType(BuiltinType::LitInt) &&
+      llvm::APFloat::getSizeInBits(astContext.getFloatTypeSemantics(toType)) ==
+          32)
+    hint.setHint(astContext.IntTy);
+  // TODO: We could provide other useful hints. For instance:
+  // For the case of toType being a boolean, if the fromType is a literal float,
+  // we could provide a FloatTy hint and if the fromType is a literal integer,
+  // we could provide an IntTy hint. The front-end, however, seems to deduce the
+  // correct type in these cases; therefore we currently don't provide any
+  // additional hints.
+
   switch (expr->getCastKind()) {
   case CastKind::CK_LValueToRValue:
     return loadIfGLValue(subExpr);

+ 7 - 0
tools/clang/test/CodeGenSPIRV/cast.2fp.implicit.hlsl

@@ -60,4 +60,11 @@ void main() {
 // CHECK-NEXT: [[vc3:%\d+]] = OpConvertSToF %v3float [[vfrom3]]
 // CHECK-NEXT: OpStore %vf3 [[vc3]]
     vf3 = vfrom3;
+
+// CHECK:                 [[a:%\d+]] = OpLoad %bool %a
+// CHECK-NEXT:        [[int_a:%\d+]] = OpSelect %int [[a]] %int_1 %int_0
+// CHECK-NEXT: [[zero_minus_a:%\d+]] = OpISub %int %int_0 [[int_a]]
+// CHECK-NEXT:              {{%\d+}} = OpConvertSToF %float [[zero_minus_a]]
+    bool a = false;
+    float c = 0-a;
 }

+ 1 - 3
tools/clang/test/CodeGenSPIRV/ternary-op.cond-op.hlsl

@@ -90,9 +90,7 @@ void main() {
     float a = cond ? 1 : 0;
 
 // CHECK:      [[c_long:%\d+]] = OpSelect %long {{%\d+}} %long_3000000000 %long_4000000000
-// CHECK-NEXT:        {{%\d+}} = OpConvertSToF %float [[c_long]]
-    // TODO: Use OpSConvert to first convert long to int. Then use OpConvertSToF.
-    float c = cond ? 3000000000 : 4000000000;
+    double c = cond ? 3000000000 : 4000000000;
 
 // CHECK:      [[d_int:%\d+]] = OpSelect %uint {{%\d+}} %uint_1 %uint_0
     uint d = cond ? 1 : 0;