Avoid DSL usage when emitting `DFdy`.

The existing code generated a kind of goofy swizzle (RTFlip.y.xxxx)
whereas the new code generates a more direct swizzle (RTFlip.yyyy).
This led to some substantial ripple effects in the SPIR-V output,
so I'm landing this as a standalone change just to be cautious.

Change-Id: Ib90a3a0938e8329c9e6a0d1a7fdf71650186e9de
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/695959
Reviewed-by: Arman Uguray <armansito@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Arman Uguray <armansito@google.com>
diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
index fcc7c45..f02e2fd 100644
--- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
@@ -56,6 +56,7 @@
 #include "src/sksl/ir/SkSLIndexExpression.h"
 #include "src/sksl/ir/SkSLInterfaceBlock.h"
 #include "src/sksl/ir/SkSLLiteral.h"
+#include "src/sksl/ir/SkSLPoison.h"
 #include "src/sksl/ir/SkSLPostfixExpression.h"
 #include "src/sksl/ir/SkSLPrefixExpression.h"
 #include "src/sksl/ir/SkSLProgram.h"
@@ -1564,13 +1565,15 @@
             this->writeWord(fn, out);
             if (!fProgram.fConfig->fSettings.fForceNoRTFlip) {
                 this->addRTFlipUniform(c.fPosition);
-                using namespace dsl;
-                DSLExpression rtFlip(
-                        ThreadContext::Compiler().convertIdentifier(Position(), SKSL_RTFLIP_NAME));
-                SpvId rtFlipY = this->vectorize(*rtFlip.y().release(), callType.columns(), out);
+                ComponentArray componentArray;
+                for (int index = 0; index < callType.columns(); ++index) {
+                    componentArray.push_back(SwizzleComponent::Y);
+                }
+                SpvId rtFlipY = this->writeSwizzle(*this->identifier(SKSL_RTFLIP_NAME),
+                                                   componentArray, out);
                 SpvId flipped = this->nextId(&callType);
-                this->writeInstruction(
-                        SpvOpFMul, this->getType(callType), flipped, result, rtFlipY, out);
+                this->writeInstruction(SpvOpFMul, this->getType(callType), flipped, result,
+                                       rtFlipY, out);
                 result = flipped;
             }
             break;
@@ -2521,6 +2524,12 @@
     }
 }
 
+std::unique_ptr<Expression> SPIRVCodeGenerator::identifier(std::string_view name) {
+    std::unique_ptr<Expression> expr = ThreadContext::Compiler().convertIdentifier(Position(),name);
+    return expr ? std::move(expr)
+                : Poison::Make(Position(), fContext);
+}
+
 SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, OutputStream& out) {
     const Variable* variable = ref.variable();
     switch (variable->modifiers().fLayout.fBuiltin) {
@@ -2682,25 +2691,32 @@
     return getLValue(f, out)->load(out);
 }
 
-SpvId SPIRVCodeGenerator::writeSwizzle(const Swizzle& swizzle, OutputStream& out) {
-    SpvId base = this->writeExpression(*swizzle.base(), out);
-    size_t count = swizzle.components().size();
+SpvId SPIRVCodeGenerator::writeSwizzle(const Expression& baseExpr,
+                                       const ComponentArray& components,
+                                       OutputStream& out) {
+    size_t count = components.size();
+    const Type& type = baseExpr.type().componentType().toCompound(fContext, count, /*rows=*/1);
+    SpvId base = this->writeExpression(baseExpr, out);
     if (count == 1) {
-        return this->writeOpCompositeExtract(swizzle.type(), base, swizzle.components()[0], out);
+        return this->writeOpCompositeExtract(type, base, components[0], out);
     }
 
-    SpvId result = this->nextId(&swizzle.type());
+    SpvId result = this->nextId(&type);
     this->writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) count, out);
-    this->writeWord(this->getType(swizzle.type()), out);
+    this->writeWord(this->getType(type), out);
     this->writeWord(result, out);
     this->writeWord(base, out);
     this->writeWord(base, out);
-    for (int component : swizzle.components()) {
+    for (int component : components) {
         this->writeWord(component, out);
     }
     return result;
 }
 
+SpvId SPIRVCodeGenerator::writeSwizzle(const Swizzle& swizzle, OutputStream& out) {
+    return this->writeSwizzle(*swizzle.base(), swizzle.components(), out);
+}
+
 SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType,
                                                const Type& operandType, SpvId lhs,
                                                SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt,
@@ -4050,7 +4066,9 @@
                     main.parameters()[0]->type().description() + "' to main()");
             return {};
         }
-        args.push_back(dsl::Float2(0).release());
+        double kZero[2] = {0.0, 0.0};
+        args.push_back(ConstructorCompound::MakeFromConstants(fContext, Position{},
+                                                              *fContext.fTypes.fFloat2, kZero));
     }
     auto callMainFn = std::make_unique<FunctionCall>(Position(), &main.returnType(), &main,
                                                      std::move(args));
diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h
index 0085096..735c45b 100644
--- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h
@@ -294,6 +294,10 @@
 
     SpvId writeFieldAccess(const FieldAccess& f, OutputStream& out);
 
+    SpvId writeSwizzle(const Expression& baseExpr,
+                       const ComponentArray& components,
+                       OutputStream& out);
+
     SpvId writeSwizzle(const Swizzle& swizzle, OutputStream& out);
 
     /**
@@ -516,6 +520,8 @@
 
     void addRTFlipUniform(Position pos);
 
+    std::unique_ptr<Expression> identifier(std::string_view name);
+
     std::tuple<const Variable*, const Variable*> synthesizeTextureAndSampler(
             const Variable& combinedSampler);
 
diff --git a/tests/sksl/intrinsics/DFdy.asm.frag b/tests/sksl/intrinsics/DFdy.asm.frag
index b81d21d..94feb71 100644
--- a/tests/sksl/intrinsics/DFdy.asm.frag
+++ b/tests/sksl/intrinsics/DFdy.asm.frag
@@ -33,17 +33,17 @@
 OpDecorate %43 RelaxedPrecision
 OpDecorate %49 RelaxedPrecision
 OpDecorate %50 RelaxedPrecision
+OpDecorate %54 RelaxedPrecision
 OpDecorate %55 RelaxedPrecision
-OpDecorate %56 RelaxedPrecision
+OpDecorate %64 RelaxedPrecision
 OpDecorate %65 RelaxedPrecision
-OpDecorate %66 RelaxedPrecision
-OpDecorate %72 RelaxedPrecision
-OpDecorate %73 RelaxedPrecision
-OpDecorate %82 RelaxedPrecision
-OpDecorate %87 RelaxedPrecision
-OpDecorate %142 RelaxedPrecision
-OpDecorate %145 RelaxedPrecision
-OpDecorate %146 RelaxedPrecision
+OpDecorate %70 RelaxedPrecision
+OpDecorate %71 RelaxedPrecision
+OpDecorate %80 RelaxedPrecision
+OpDecorate %84 RelaxedPrecision
+OpDecorate %136 RelaxedPrecision
+OpDecorate %139 RelaxedPrecision
+OpDecorate %140 RelaxedPrecision
 %bool = OpTypeBool
 %_ptr_Input_bool = OpTypePointer Input %bool
 %sk_Clockwise = OpVariable %_ptr_Input_bool Input
@@ -74,8 +74,8 @@
 %v3bool = OpTypeVector %bool 3
 %v4bool = OpTypeVector %bool 4
 %float_1 = OpConstant %float 1
-%118 = OpConstantComposite %v2float %float_1 %float_1
-%132 = OpConstantComposite %v2float %float_0 %float_1
+%113 = OpConstantComposite %v2float %float_1 %float_1
+%126 = OpConstantComposite %v2float %float_0 %float_1
 %int_1 = OpConstant %int 1
 %int_2 = OpConstant %int 2
 %_entrypoint_v = OpFunction %void None %17
@@ -90,7 +90,7 @@
 %25 = OpFunctionParameter %_ptr_Function_v2float
 %26 = OpLabel
 %expected = OpVariable %_ptr_Function_v4float Function
-%136 = OpVariable %_ptr_Function_v4float Function
+%130 = OpVariable %_ptr_Function_v4float Function
 OpStore %expected %29
 %32 = OpAccessChain %_ptr_Uniform_v4float %11 %int_0
 %36 = OpLoad %v4float %32
@@ -110,112 +110,106 @@
 %47 = OpDPdy %v2float %50
 %51 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
 %52 = OpLoad %v2float %51
-%53 = OpCompositeExtract %float %52 1
-%54 = OpCompositeConstruct %v2float %53 %53
-%55 = OpFMul %v2float %47 %54
-%56 = OpVectorShuffle %v2float %29 %29 0 1
-%57 = OpFOrdEqual %v2bool %55 %56
-%59 = OpAll %bool %57
+%53 = OpVectorShuffle %v2float %52 %52 1 1
+%54 = OpFMul %v2float %47 %53
+%55 = OpVectorShuffle %v2float %29 %29 0 1
+%56 = OpFOrdEqual %v2bool %54 %55
+%58 = OpAll %bool %56
 OpBranch %46
 %46 = OpLabel
-%60 = OpPhi %bool %false %26 %59 %45
-OpSelectionMerge %62 None
-OpBranchConditional %60 %61 %62
+%59 = OpPhi %bool %false %26 %58 %45
+OpSelectionMerge %61 None
+OpBranchConditional %59 %60 %61
+%60 = OpLabel
+%63 = OpAccessChain %_ptr_Uniform_v4float %11 %int_0
+%64 = OpLoad %v4float %63
+%65 = OpVectorShuffle %v3float %64 %64 0 1 2
+%62 = OpDPdy %v3float %65
+%67 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
+%68 = OpLoad %v2float %67
+%69 = OpVectorShuffle %v3float %68 %68 1 1 1
+%70 = OpFMul %v3float %62 %69
+%71 = OpVectorShuffle %v3float %29 %29 0 1 2
+%72 = OpFOrdEqual %v3bool %70 %71
+%74 = OpAll %bool %72
+OpBranch %61
 %61 = OpLabel
-%64 = OpAccessChain %_ptr_Uniform_v4float %11 %int_0
-%65 = OpLoad %v4float %64
-%66 = OpVectorShuffle %v3float %65 %65 0 1 2
-%63 = OpDPdy %v3float %66
-%68 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
-%69 = OpLoad %v2float %68
-%70 = OpCompositeExtract %float %69 1
-%71 = OpCompositeConstruct %v3float %70 %70 %70
-%72 = OpFMul %v3float %63 %71
-%73 = OpVectorShuffle %v3float %29 %29 0 1 2
-%74 = OpFOrdEqual %v3bool %72 %73
-%76 = OpAll %bool %74
-OpBranch %62
-%62 = OpLabel
-%77 = OpPhi %bool %false %46 %76 %61
-OpSelectionMerge %79 None
-OpBranchConditional %77 %78 %79
-%78 = OpLabel
-%81 = OpAccessChain %_ptr_Uniform_v4float %11 %int_0
-%82 = OpLoad %v4float %81
-%80 = OpDPdy %v4float %82
-%83 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
-%84 = OpLoad %v2float %83
-%85 = OpCompositeExtract %float %84 1
-%86 = OpCompositeConstruct %v4float %85 %85 %85 %85
-%87 = OpFMul %v4float %80 %86
-%88 = OpFOrdEqual %v4bool %87 %29
-%90 = OpAll %bool %88
-OpBranch %79
-%79 = OpLabel
-%91 = OpPhi %bool %false %62 %90 %78
-OpSelectionMerge %93 None
-OpBranchConditional %91 %92 %93
-%92 = OpLabel
-%96 = OpLoad %v2float %25
-%97 = OpVectorShuffle %v2float %96 %96 0 0
-%95 = OpDPdy %v2float %97
-%98 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
-%99 = OpLoad %v2float %98
-%100 = OpCompositeExtract %float %99 1
-%101 = OpCompositeConstruct %v2float %100 %100
-%102 = OpFMul %v2float %95 %101
-%94 = OpExtInst %v2float %1 FSign %102
-%103 = OpFOrdEqual %v2bool %94 %20
-%104 = OpAll %bool %103
-OpBranch %93
-%93 = OpLabel
-%105 = OpPhi %bool %false %79 %104 %92
-OpSelectionMerge %107 None
-OpBranchConditional %105 %106 %107
-%106 = OpLabel
-%110 = OpLoad %v2float %25
-%111 = OpVectorShuffle %v2float %110 %110 1 1
-%109 = OpDPdy %v2float %111
-%112 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
-%113 = OpLoad %v2float %112
-%114 = OpCompositeExtract %float %113 1
-%115 = OpCompositeConstruct %v2float %114 %114
-%116 = OpFMul %v2float %109 %115
-%108 = OpExtInst %v2float %1 FSign %116
-%119 = OpFOrdEqual %v2bool %108 %118
-%120 = OpAll %bool %119
-OpBranch %107
-%107 = OpLabel
-%121 = OpPhi %bool %false %93 %120 %106
-OpSelectionMerge %123 None
-OpBranchConditional %121 %122 %123
-%122 = OpLabel
-%126 = OpLoad %v2float %25
-%125 = OpDPdy %v2float %126
-%127 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
-%128 = OpLoad %v2float %127
-%129 = OpCompositeExtract %float %128 1
-%130 = OpCompositeConstruct %v2float %129 %129
-%131 = OpFMul %v2float %125 %130
-%124 = OpExtInst %v2float %1 FSign %131
-%133 = OpFOrdEqual %v2bool %124 %132
-%134 = OpAll %bool %133
-OpBranch %123
-%123 = OpLabel
-%135 = OpPhi %bool %false %107 %134 %122
-OpSelectionMerge %139 None
-OpBranchConditional %135 %137 %138
-%137 = OpLabel
-%140 = OpAccessChain %_ptr_Uniform_v4float %11 %int_1
-%142 = OpLoad %v4float %140
-OpStore %136 %142
-OpBranch %139
-%138 = OpLabel
-%143 = OpAccessChain %_ptr_Uniform_v4float %11 %int_2
-%145 = OpLoad %v4float %143
-OpStore %136 %145
-OpBranch %139
-%139 = OpLabel
-%146 = OpLoad %v4float %136
-OpReturnValue %146
+%75 = OpPhi %bool %false %46 %74 %60
+OpSelectionMerge %77 None
+OpBranchConditional %75 %76 %77
+%76 = OpLabel
+%79 = OpAccessChain %_ptr_Uniform_v4float %11 %int_0
+%80 = OpLoad %v4float %79
+%78 = OpDPdy %v4float %80
+%81 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
+%82 = OpLoad %v2float %81
+%83 = OpVectorShuffle %v4float %82 %82 1 1 1 1
+%84 = OpFMul %v4float %78 %83
+%85 = OpFOrdEqual %v4bool %84 %29
+%87 = OpAll %bool %85
+OpBranch %77
+%77 = OpLabel
+%88 = OpPhi %bool %false %61 %87 %76
+OpSelectionMerge %90 None
+OpBranchConditional %88 %89 %90
+%89 = OpLabel
+%93 = OpLoad %v2float %25
+%94 = OpVectorShuffle %v2float %93 %93 0 0
+%92 = OpDPdy %v2float %94
+%95 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
+%96 = OpLoad %v2float %95
+%97 = OpVectorShuffle %v2float %96 %96 1 1
+%98 = OpFMul %v2float %92 %97
+%91 = OpExtInst %v2float %1 FSign %98
+%99 = OpFOrdEqual %v2bool %91 %20
+%100 = OpAll %bool %99
+OpBranch %90
+%90 = OpLabel
+%101 = OpPhi %bool %false %77 %100 %89
+OpSelectionMerge %103 None
+OpBranchConditional %101 %102 %103
+%102 = OpLabel
+%106 = OpLoad %v2float %25
+%107 = OpVectorShuffle %v2float %106 %106 1 1
+%105 = OpDPdy %v2float %107
+%108 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
+%109 = OpLoad %v2float %108
+%110 = OpVectorShuffle %v2float %109 %109 1 1
+%111 = OpFMul %v2float %105 %110
+%104 = OpExtInst %v2float %1 FSign %111
+%114 = OpFOrdEqual %v2bool %104 %113
+%115 = OpAll %bool %114
+OpBranch %103
+%103 = OpLabel
+%116 = OpPhi %bool %false %90 %115 %102
+OpSelectionMerge %118 None
+OpBranchConditional %116 %117 %118
+%117 = OpLabel
+%121 = OpLoad %v2float %25
+%120 = OpDPdy %v2float %121
+%122 = OpAccessChain %_ptr_Uniform_v2float %11 %int_3
+%123 = OpLoad %v2float %122
+%124 = OpVectorShuffle %v2float %123 %123 1 1
+%125 = OpFMul %v2float %120 %124
+%119 = OpExtInst %v2float %1 FSign %125
+%127 = OpFOrdEqual %v2bool %119 %126
+%128 = OpAll %bool %127
+OpBranch %118
+%118 = OpLabel
+%129 = OpPhi %bool %false %103 %128 %117
+OpSelectionMerge %133 None
+OpBranchConditional %129 %131 %132
+%131 = OpLabel
+%134 = OpAccessChain %_ptr_Uniform_v4float %11 %int_1
+%136 = OpLoad %v4float %134
+OpStore %130 %136
+OpBranch %133
+%132 = OpLabel
+%137 = OpAccessChain %_ptr_Uniform_v4float %11 %int_2
+%139 = OpLoad %v4float %137
+OpStore %130 %139
+OpBranch %133
+%133 = OpLabel
+%140 = OpLoad %v4float %130
+OpReturnValue %140
 OpFunctionEnd
diff --git a/tests/sksl/intrinsics/DFdy.hlsl b/tests/sksl/intrinsics/DFdy.hlsl
index b436642..ac3ad73 100644
--- a/tests/sksl/intrinsics/DFdy.hlsl
+++ b/tests/sksl/intrinsics/DFdy.hlsl
@@ -17,76 +17,76 @@
 float4 main(float2 _25)
 {
     float4 expected = 0.0f.xxxx;
-    bool _60 = false;
+    bool _59 = false;
     if ((ddy(_11_testInputs.x) * _11_u_skRTFlip.y) == 0.0f)
     {
-        float2 _55 = ddy(_11_testInputs.xy) * _11_u_skRTFlip.y.xx;
-        _60 = all(bool2(_55.x == 0.0f.xxxx.xy.x, _55.y == 0.0f.xxxx.xy.y));
+        float2 _54 = ddy(_11_testInputs.xy) * _11_u_skRTFlip.yy;
+        _59 = all(bool2(_54.x == 0.0f.xxxx.xy.x, _54.y == 0.0f.xxxx.xy.y));
     }
     else
     {
-        _60 = false;
+        _59 = false;
     }
-    bool _77 = false;
-    if (_60)
+    bool _75 = false;
+    if (_59)
     {
-        float3 _72 = ddy(_11_testInputs.xyz) * _11_u_skRTFlip.y.xxx;
-        _77 = all(bool3(_72.x == 0.0f.xxxx.xyz.x, _72.y == 0.0f.xxxx.xyz.y, _72.z == 0.0f.xxxx.xyz.z));
+        float3 _70 = ddy(_11_testInputs.xyz) * _11_u_skRTFlip.yyy;
+        _75 = all(bool3(_70.x == 0.0f.xxxx.xyz.x, _70.y == 0.0f.xxxx.xyz.y, _70.z == 0.0f.xxxx.xyz.z));
     }
     else
     {
-        _77 = false;
+        _75 = false;
     }
-    bool _91 = false;
-    if (_77)
+    bool _88 = false;
+    if (_75)
     {
-        float4 _87 = ddy(_11_testInputs) * _11_u_skRTFlip.y.xxxx;
-        _91 = all(bool4(_87.x == 0.0f.xxxx.x, _87.y == 0.0f.xxxx.y, _87.z == 0.0f.xxxx.z, _87.w == 0.0f.xxxx.w));
+        float4 _84 = ddy(_11_testInputs) * _11_u_skRTFlip.yyyy;
+        _88 = all(bool4(_84.x == 0.0f.xxxx.x, _84.y == 0.0f.xxxx.y, _84.z == 0.0f.xxxx.z, _84.w == 0.0f.xxxx.w));
     }
     else
     {
-        _91 = false;
+        _88 = false;
     }
-    bool _105 = false;
-    if (_91)
+    bool _101 = false;
+    if (_88)
     {
-        float2 _94 = sign(ddy(_25.xx) * _11_u_skRTFlip.y.xx);
-        _105 = all(bool2(_94.x == 0.0f.xx.x, _94.y == 0.0f.xx.y));
+        float2 _91 = sign(ddy(_25.xx) * _11_u_skRTFlip.yy);
+        _101 = all(bool2(_91.x == 0.0f.xx.x, _91.y == 0.0f.xx.y));
     }
     else
     {
-        _105 = false;
+        _101 = false;
     }
-    bool _121 = false;
-    if (_105)
+    bool _116 = false;
+    if (_101)
     {
-        float2 _108 = sign(ddy(_25.yy) * _11_u_skRTFlip.y.xx);
-        _121 = all(bool2(_108.x == 1.0f.xx.x, _108.y == 1.0f.xx.y));
+        float2 _104 = sign(ddy(_25.yy) * _11_u_skRTFlip.yy);
+        _116 = all(bool2(_104.x == 1.0f.xx.x, _104.y == 1.0f.xx.y));
     }
     else
     {
-        _121 = false;
+        _116 = false;
     }
-    bool _135 = false;
-    if (_121)
+    bool _129 = false;
+    if (_116)
     {
-        float2 _124 = sign(ddy(_25) * _11_u_skRTFlip.y.xx);
-        _135 = all(bool2(_124.x == float2(0.0f, 1.0f).x, _124.y == float2(0.0f, 1.0f).y));
+        float2 _119 = sign(ddy(_25) * _11_u_skRTFlip.yy);
+        _129 = all(bool2(_119.x == float2(0.0f, 1.0f).x, _119.y == float2(0.0f, 1.0f).y));
     }
     else
     {
-        _135 = false;
+        _129 = false;
     }
-    float4 _136 = 0.0f.xxxx;
-    if (_135)
+    float4 _130 = 0.0f.xxxx;
+    if (_129)
     {
-        _136 = _11_colorGreen;
+        _130 = _11_colorGreen;
     }
     else
     {
-        _136 = _11_colorRed;
+        _130 = _11_colorRed;
     }
-    return _136;
+    return _130;
 }
 
 void frag_main()
diff --git a/tests/sksl/intrinsics/SampleGrad.asm.frag b/tests/sksl/intrinsics/SampleGrad.asm.frag
index cc1d7d8..195270d 100644
--- a/tests/sksl/intrinsics/SampleGrad.asm.frag
+++ b/tests/sksl/intrinsics/SampleGrad.asm.frag
@@ -65,9 +65,8 @@
 %32 = OpDPdy %v2float %33
 %39 = OpAccessChain %_ptr_Uniform_v2float %34 %int_0
 %41 = OpLoad %v2float %39
-%42 = OpCompositeExtract %float %41 1
-%43 = OpCompositeConstruct %v2float %42 %42
-%44 = OpFMul %v2float %32 %43
-%27 = OpImageSampleExplicitLod %v4float %28 %29 Grad %30 %44
+%42 = OpVectorShuffle %v2float %41 %41 1 1
+%43 = OpFMul %v2float %32 %42
+%27 = OpImageSampleExplicitLod %v4float %28 %29 Grad %30 %43
 OpReturnValue %27
 OpFunctionEnd
diff --git a/tests/sksl/intrinsics/SampleGrad.hlsl b/tests/sksl/intrinsics/SampleGrad.hlsl
index 43ad520..7eae6f8 100644
--- a/tests/sksl/intrinsics/SampleGrad.hlsl
+++ b/tests/sksl/intrinsics/SampleGrad.hlsl
@@ -15,7 +15,7 @@
 
 float4 main(float2 _25)
 {
-    return t.SampleGrad(_t_sampler, _25, ddx(_25), ddy(_25) * _34_u_skRTFlip.y.xx);
+    return t.SampleGrad(_t_sampler, _25, ddx(_25), ddy(_25) * _34_u_skRTFlip.yy);
 }
 
 void frag_main()