1 /*
  2  * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package hat.phases;
 26 
 27 import hat.Accelerator;
 28 import hat.dialect.HATLocalVarOp;
 29 import hat.dialect.HATPhaseUtils;
 30 import hat.dialect.HATPrivateVarOp;
 31 import hat.dialect.HATVectorAddOp;
 32 import hat.dialect.HATVectorDivOp;
 33 import hat.dialect.HATVectorLoadOp;
 34 import hat.dialect.HATVectorMakeOfOp;
 35 import hat.dialect.HATVectorMulOp;
 36 import hat.dialect.HATVectorOfOp;
 37 import hat.dialect.HATVectorSubOp;
 38 import hat.dialect.HATVectorVarLoadOp;
 39 import hat.dialect.HATVectorVarOp;
 40 import hat.dialect.HATVectorOp;
 41 import hat.dialect.HATVectorBinaryOp;
 42 import hat.optools.OpTk;
 43 import hat.types._V;
 44 import jdk.incubator.code.Block;
 45 import jdk.incubator.code.CodeElement;
 46 import jdk.incubator.code.CopyContext;
 47 import jdk.incubator.code.Op;
 48 import jdk.incubator.code.TypeElement;
 49 import jdk.incubator.code.Value;
 50 import jdk.incubator.code.dialect.core.CoreOp;
 51 import jdk.incubator.code.dialect.java.JavaOp;
 52 
 53 import java.util.HashMap;
 54 import java.util.List;
 55 import java.util.Map;
 56 import java.util.Objects;
 57 import java.util.Set;
 58 import java.util.stream.Collectors;
 59 import java.util.stream.Stream;
 60 
 61 import static hat.dialect.HATPhaseUtils.VectorMetaData;
 62 import static hat.dialect.HATPhaseUtils.findNameVector;
 63 import static hat.dialect.HATPhaseUtils.findVectorTypeElement;
 64 import static hat.dialect.HATPhaseUtils.getVectorTypeInfo;
 65 import static hat.dialect.HATPhaseUtils.getWitdh;
 66 
 67 public abstract class HATDialectifyVectorOpPhase implements HATDialect {
 68 
 69     protected final Accelerator accelerator;
 70 
 71     @Override
 72     public Accelerator accelerator() {
 73         return this.accelerator;
 74     }
 75 
 76     private final OpView vectorOperation;
 77 
 78     public HATDialectifyVectorOpPhase(Accelerator accelerator, OpView vectorOperation) {
 79         this.accelerator = accelerator;
 80         this.vectorOperation = vectorOperation;
 81     }
 82 
 83     private HATVectorBinaryOp.OpType getBinaryOpType(JavaOp.InvokeOp invokeOp) {
 84         return switch (invokeOp.invokeDescriptor().name()) {
 85             case "add" -> HATVectorBinaryOp.OpType.ADD;
 86             case "sub" -> HATVectorBinaryOp.OpType.SUB;
 87             case "mul" -> HATVectorBinaryOp.OpType.MUL;
 88             case "div" -> HATVectorBinaryOp.OpType.DIV;
 89             default -> throw new RuntimeException("Unknown binary op " + invokeOp.invokeDescriptor().name());
 90         };
 91     }
 92 
 93     public enum OpView {
 94         FLOAT4_LOAD("float4View"),
 95         FLOAT2_LOAD("float2View"),
 96         OF("of"),
 97         ADD("add"),
 98         SUB("sub"),
 99         MUL("mul"),
100         DIV("div"),
101         MAKE_MUTABLE("makeMutable");
102         final String methodName;
103 
104         OpView(String methodName) {
105             this.methodName = methodName;
106         }
107     }
108 
109     private boolean isVectorOperation(JavaOp.InvokeOp invokeOp) {
110         TypeElement typeElement = invokeOp.resultType();
111         Set<Class<?>> interfaces = Set.of();
112         try {
113             Class<?> aClass = Class.forName(typeElement.toString());
114             interfaces = HATPhaseUtils.inspectAllInterfaces(aClass);
115         } catch (ClassNotFoundException _) {
116         }
117         return interfaces.contains(_V.class) && isMethod(invokeOp, vectorOperation.methodName);
118     }
119 
120     private boolean findIsSharedOrPrivate(CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
121         return findIsSharedOrPrivate(varLoadOp.operands().get(0));
122     }
123 
124     private boolean findIsSharedOrPrivate(Value v) {
125         if (v instanceof Op.Result r && r.op() instanceof CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
126             return findIsSharedOrPrivate(varLoadOp);
127         } else {
128             if (v instanceof CoreOp.Result r && (r.op() instanceof HATLocalVarOp || r.op() instanceof HATPrivateVarOp)) {
129                 return true;
130             }
131             return false;
132         }
133     }
134 
135     private HATVectorBinaryOp buildVectorBinaryOp(HATVectorBinaryOp.OpType opType, String varName, TypeElement resultType, TypeElement vectorElementType, int witdh, List<Value> outputOperands) {
136         return switch (opType) {
137             case ADD -> new HATVectorAddOp(varName, resultType, vectorElementType, witdh, outputOperands);
138             case SUB -> new HATVectorSubOp(varName, resultType, vectorElementType, witdh, outputOperands);
139             case MUL -> new HATVectorMulOp(varName, resultType, vectorElementType, witdh, outputOperands);
140             case DIV -> new HATVectorDivOp(varName, resultType, vectorElementType, witdh, outputOperands);
141         };
142     }
143 
144     private void insertVectorLoadOp(Block.Builder blockBuilder, JavaOp.InvokeOp invokeOp, CoreOp.VarOp varOp, boolean isShared) {
145         List<Value> inputOperandsVarOp = invokeOp.operands();
146         List<Value> outputOperandsVarOp = blockBuilder.context().getValues(inputOperandsVarOp);
147         VectorMetaData metaData = getVectorTypeInfo(invokeOp);
148         HATVectorOp memoryViewOp = new HATVectorLoadOp(varOp.varName(), varOp.resultType(), metaData.vectorTypeElement(), metaData.lanes(), isShared, outputOperandsVarOp);
149         Op.Result hatLocalResult = blockBuilder.op(memoryViewOp);
150         memoryViewOp.setLocation(varOp.location());
151         blockBuilder.context().mapValue(invokeOp.result(), hatLocalResult);
152     }
153 
154     private void inertVectorVarOp(Block.Builder blockBuilder, CoreOp.VarOp varOp, Map<Op, VectorMetaData> vectorMetaData) {
155         List<Value> inputOperandsVarOp = varOp.operands();
156         List<Value> outputOperandsVarOp = blockBuilder.context().getValues(inputOperandsVarOp);
157         VectorMetaData vmd = vectorMetaData.get(varOp);
158         HATVectorOp memoryViewOp = new HATVectorVarOp(varOp.varName(), varOp.resultType(), vmd.vectorTypeElement(), vmd.lanes(), outputOperandsVarOp);
159         Op.Result hatLocalResult = blockBuilder.op(memoryViewOp);
160         memoryViewOp.setLocation(varOp.location());
161         blockBuilder.context().mapValue(varOp.result(), hatLocalResult);
162     }
163 
164     public void insertBinaryOp(Block.Builder blockBuilder, CoreOp.VarOp varOp, JavaOp.InvokeOp invokeOp, Map<Op, VectorMetaData> vectorMetaData, Map<JavaOp.InvokeOp, HATVectorBinaryOp.OpType> binaryOperation) {
165         List<Value> inputOperands = invokeOp.operands();
166         List<Value> outputOperands = blockBuilder.context().getValues(inputOperands);
167         HATVectorBinaryOp.OpType binaryOpType = binaryOperation.get(invokeOp);
168         VectorMetaData vmd = vectorMetaData.get(invokeOp);
169         HATVectorOp memoryViewOp = buildVectorBinaryOp(binaryOpType, varOp.varName(), invokeOp.resultType(), vmd.vectorTypeElement(), vmd.lanes(), outputOperands);
170         Op.Result hatVectorOpResult = blockBuilder.op(memoryViewOp);
171         memoryViewOp.setLocation(varOp.location());
172         blockBuilder.context().mapValue(invokeOp.result(), hatVectorOpResult);
173     }
174 
175     private void insertVectorVarLoadOp(Block.Builder blockBuilder, CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
176         List<Value> inputOperandsVarLoad = varLoadOp.operands();
177         List<Value> outputOperandsVarLoad = blockBuilder.context().getValues(inputOperandsVarLoad);
178         String varLoadName = findNameVector(varLoadOp);
179         int lanes = getWitdh(varLoadOp);
180         TypeElement vectorElementType = findVectorTypeElement(varLoadOp);
181         HATVectorOp memoryViewOp = new HATVectorVarLoadOp(varLoadName, varLoadOp.resultType(), vectorElementType, lanes, outputOperandsVarLoad);
182         Op.Result hatVectorResult = blockBuilder.op(memoryViewOp);
183         memoryViewOp.setLocation(varLoadOp.location());
184         blockBuilder.context().mapValue(varLoadOp.result(), hatVectorResult);
185     }
186 
187     public void insertVectorBinaryOp(Block.Builder blockBuilder, JavaOp.InvokeOp invokeOp, Map<JavaOp.InvokeOp, HATVectorBinaryOp.OpType> binaryOperation) {
188         List<Value> inputOperands = invokeOp.operands();
189         List<Value> outputOperands = blockBuilder.context().getValues(inputOperands);
190         VectorMetaData vectorMetaData = getVectorTypeInfo(invokeOp);
191         HATVectorOp memoryViewOp = buildVectorBinaryOp(binaryOperation.get(invokeOp), "null", invokeOp.resultType(), vectorMetaData.vectorTypeElement(), vectorMetaData.lanes(), outputOperands);
192         Op.Result hatVectorOpResult = blockBuilder.op(memoryViewOp);
193         memoryViewOp.setLocation(invokeOp.location());
194         blockBuilder.context().mapValue(invokeOp.result(), hatVectorOpResult);
195     }
196 
197     public void insertVectorOfOp(Block.Builder blockBuilder, JavaOp.InvokeOp invokeOp, Map<Op, VectorMetaData> vectorMetaData) {
198         List<Value> inputOperandsVarOp = invokeOp.operands();
199         List<Value> outputOperandsVarOp = blockBuilder.context().getValues(inputOperandsVarOp);
200         VectorMetaData vmd = vectorMetaData.get(invokeOp);
201         HATVectorOfOp memoryViewOp = new HATVectorOfOp(invokeOp.resultType(), vmd.vectorTypeElement(), vmd.lanes(), outputOperandsVarOp);
202         Op.Result hatLocalResult = blockBuilder.op(memoryViewOp);
203         memoryViewOp.setLocation(invokeOp.location());
204         blockBuilder.context().mapValue(invokeOp.result(), hatLocalResult);
205     }
206 
207     public void insertVectorMakeOfOp(Block.Builder blockBuilder, JavaOp.InvokeOp invokeOp, Map<Op, VectorMetaData> vectorMetaData) {
208         List<Value> inputOperandsVarOp = invokeOp.operands();
209         List<Value> outputOperandsVarOp = blockBuilder.context().getValues(inputOperandsVarOp);
210         String varName = findNameVector(invokeOp.operands().getFirst());
211         VectorMetaData vmd = vectorMetaData.get(invokeOp);
212         HATVectorMakeOfOp makeOf = new HATVectorMakeOfOp(varName, invokeOp.resultType(), vmd.lanes(), outputOperandsVarOp);
213         Op.Result hatLocalResult = blockBuilder.op(makeOf);
214         makeOf.setLocation(invokeOp.location());
215         blockBuilder.context().mapValue(invokeOp.result(), hatLocalResult);
216     }
217 
218     private CoreOp.FuncOp dialectifyVectorLoad(CoreOp.FuncOp funcOp) {
219         var here = OpTk.CallSite.of(this.getClass(), "dialectifyVectorLoad");
220         Map<Op, VectorMetaData> vectorMetaData = new HashMap<>();
221         before(here, funcOp);
222         Stream<CodeElement<?, ?>> float4NodesInvolved = funcOp.elements()
223                 .mapMulti((codeElement, consumer) -> {
224                     if (codeElement instanceof CoreOp.VarOp varOp) {
225                         List<Value> inputOperandsVarOp = varOp.operands();
226                         for (Value inputOperand : inputOperandsVarOp) {
227                             if (inputOperand instanceof Op.Result result) {
228                                 if (result.op() instanceof JavaOp.InvokeOp invokeOp) {
229                                     if (isVectorOperation(invokeOp)) {
230                                         // Associate both ops to the vectorTypeInfo for easy
231                                         // access to type and lanes
232                                         VectorMetaData vectorTypeInfo = getVectorTypeInfo(invokeOp);
233                                         vectorMetaData.put(invokeOp, vectorTypeInfo);
234                                         vectorMetaData.put(varOp, vectorTypeInfo);
235                                         consumer.accept(invokeOp);
236                                         consumer.accept(varOp);
237                                     }
238                                 }
239                             }
240                         }
241                     }
242                 });
243 
244         Set<CodeElement<?, ?>> nodesInvolved = float4NodesInvolved.collect(Collectors.toSet());
245 
246         funcOp = OpTk.transform(here, funcOp, (blockBuilder, op) -> {
247             CopyContext context = blockBuilder.context();
248             if (!nodesInvolved.contains(op)) {
249                 blockBuilder.op(op);
250             } else if (op instanceof JavaOp.InvokeOp invokeOp) {
251                 // Don't insert the invoke node
252                 Op.Result result = invokeOp.result();
253                 List<Op.Result> collect = result.uses().stream().toList();
254                 boolean isShared = findIsSharedOrPrivate(invokeOp.operands().getFirst());
255                 for (Op.Result r : collect) {
256                     if (r.op() instanceof CoreOp.VarOp varOp) {
257                         insertVectorLoadOp(blockBuilder, invokeOp, varOp, isShared);
258                     }
259                 }
260             } else if (op instanceof CoreOp.VarOp varOp) {
261                 inertVectorVarOp(blockBuilder, varOp, vectorMetaData);
262             }
263             return blockBuilder;
264         });
265         after(here, funcOp);
266         return funcOp;
267     }
268 
269     private CoreOp.FuncOp dialectifyVectorOf(CoreOp.FuncOp funcOp) {
270         var here = OpTk.CallSite.of(this.getClass(), "dialectifyVectorOf");
271         Map<Op, VectorMetaData> vectorMetaData = new HashMap<>();
272         before(here, funcOp);
273         Stream<CodeElement<?, ?>> vectorNodes = funcOp.elements()
274                 .mapMulti((codeElement, consumer) -> {
275                     if (codeElement instanceof JavaOp.InvokeOp invokeOp) {
276                         if (isVectorOperation(invokeOp)) {
277                             consumer.accept(invokeOp);
278                             Set<Op.Result> uses = invokeOp.result().uses();
279                             for (Op.Result result : uses) {
280                                 if (result.op() instanceof CoreOp.VarOp varOp) {
281                                     consumer.accept(varOp);
282                                     VectorMetaData vectorTypeInfo = getVectorTypeInfo(invokeOp);
283                                     vectorMetaData.put(invokeOp, vectorTypeInfo);
284                                     vectorMetaData.put(varOp, vectorTypeInfo);
285                                 }
286                             }
287                         }
288                     }
289                 });
290 
291         Set<CodeElement<?, ?>> nodesInvolved = vectorNodes.collect(Collectors.toSet());
292 
293         funcOp = OpTk.transform(here, funcOp, (blockBuilder, op) -> {
294             if (!nodesInvolved.contains(op)) {
295                 blockBuilder.op(op);
296             } else if (op instanceof JavaOp.InvokeOp invokeOp) {
297                 insertVectorOfOp(blockBuilder, invokeOp, vectorMetaData);
298             } else if (op instanceof CoreOp.VarOp varOp) {
299                 inertVectorVarOp(blockBuilder, varOp, vectorMetaData);
300             }
301             return blockBuilder;
302         });
303         after(here, funcOp);
304         return funcOp;
305     }
306 
307     private CoreOp.FuncOp dialectifyVectorBinaryOps(CoreOp.FuncOp funcOp) {
308         var here = OpTk.CallSite.of(this.getClass(), "dialectifyVectorBinaryOps");
309         before(here, funcOp);
310         Map<JavaOp.InvokeOp, HATVectorBinaryOp.OpType> binaryOperation = new HashMap<>();
311         Map<Op, VectorMetaData> vectorMetaData = new HashMap<>();
312 
313         Stream<CodeElement<?, ?>> float4NodesInvolved = funcOp.elements()
314                 .mapMulti((codeElement, consumer) -> {
315                     if (codeElement instanceof CoreOp.VarOp varOp) {
316                         List<Value> inputOperandsVarOp = varOp.operands();
317                         for (Value inputOperand : inputOperandsVarOp) {
318                             if (inputOperand instanceof Op.Result result) {
319                                 if (result.op() instanceof JavaOp.InvokeOp invokeOp) {
320                                     if (isVectorOperation(invokeOp)) {
321                                         HATVectorBinaryOp.OpType binaryOpType = getBinaryOpType(invokeOp);
322                                         binaryOperation.put(invokeOp, binaryOpType);
323                                         VectorMetaData vectorTypeInfo = getVectorTypeInfo(invokeOp);
324                                         vectorMetaData.put(invokeOp, vectorTypeInfo);
325                                         vectorMetaData.put(varOp, vectorTypeInfo);
326                                         consumer.accept(invokeOp);
327                                         consumer.accept(varOp);
328                                     }
329                                 }
330                             }
331                         }
332                     }
333                 });
334 
335         Set<CodeElement<?, ?>> nodesInvolved = float4NodesInvolved.collect(Collectors.toSet());
336 
337         funcOp = OpTk.transform(here, funcOp, nodesInvolved::contains, (blockBuilder, op) -> {
338             if (op instanceof JavaOp.InvokeOp invokeOp) {
339                 Op.Result result = invokeOp.result();
340                 List<Op.Result> collect = result.uses().stream().toList();
341                 for (Op.Result r : collect) {
342                     if (r.op() instanceof CoreOp.VarOp varOp) {
343                         insertBinaryOp(blockBuilder, varOp, invokeOp, vectorMetaData, binaryOperation);
344                         break;
345                     }
346                 }
347             } else if (op instanceof CoreOp.VarOp varOp) {
348                 inertVectorVarOp(blockBuilder, varOp, vectorMetaData);
349             }
350             return blockBuilder;
351         });
352         after(here, funcOp);
353         return funcOp;
354     }
355 
356     private CoreOp.FuncOp dialectifyMutableOf(CoreOp.FuncOp funcOp) {
357         var here = OpTk.CallSite.of(this.getClass(), "dialectifyMutableOf");
358         before(here, funcOp);
359         Map<Op, VectorMetaData> vectorMetaData = new HashMap<>();
360         Stream<CodeElement<?, ?>> float4NodesInvolved = funcOp.elements()
361                 .mapMulti((codeElement, consumer) -> {
362                     if (codeElement instanceof JavaOp.InvokeOp invokeOp) {
363                         if (isVectorOperation(invokeOp)) {
364                             consumer.accept(invokeOp);
365                             VectorMetaData vectorTypeInfo = getVectorTypeInfo(invokeOp);
366                             vectorMetaData.put(invokeOp, vectorTypeInfo);
367                             Set<Op.Result> uses = invokeOp.result().uses();
368                             for (Op.Result result : uses) {
369                                 if (result.op() instanceof CoreOp.VarOp varOp) {
370                                     consumer.accept(varOp);
371                                     vectorMetaData.put(varOp, vectorTypeInfo);
372                                 }
373                             }
374                         }
375                     }
376                 });
377 
378         Set<CodeElement<?, ?>> nodesInvolved = float4NodesInvolved.collect(Collectors.toSet());
379 
380         funcOp = OpTk.transform(here, funcOp, (blockBuilder, op) -> {
381             if (!nodesInvolved.contains(op)) {
382                 blockBuilder.op(op);
383             } else if (op instanceof JavaOp.InvokeOp invokeOp) {
384                 insertVectorMakeOfOp(blockBuilder, invokeOp, vectorMetaData);
385             } else if (op instanceof CoreOp.VarOp varOp) {
386                 inertVectorVarOp(blockBuilder, varOp, vectorMetaData);
387             }
388             return blockBuilder;
389         });
390         after(here, funcOp);
391         return funcOp;
392     }
393 
394     private CoreOp.FuncOp dialectifyVectorBinaryWithConcatenationOps(CoreOp.FuncOp funcOp) {
395         var here = OpTk.CallSite.of(this.getClass(), "dialectifyBinaryWithConcatenation");
396         before(here, funcOp);
397         Map<JavaOp.InvokeOp, HATVectorBinaryOp.OpType> binaryOperation = new HashMap<>();
398         Stream<CodeElement<?, ?>> vectorNodes = funcOp.elements()
399                 .mapMulti((codeElement, consumer) -> {
400                     if (codeElement instanceof JavaOp.InvokeOp invokeOp) {
401                         if (isVectorOperation(invokeOp)) {
402                             List<Value> inputOperandsInvoke = invokeOp.operands();
403                             for (Value inputOperand : inputOperandsInvoke) {
404                                 if (inputOperand instanceof Op.Result r && r.op() instanceof CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
405                                     HATVectorBinaryOp.OpType binaryOpType = getBinaryOpType(invokeOp);
406                                     binaryOperation.put(invokeOp, binaryOpType);
407                                     consumer.accept(varLoadOp);
408                                     consumer.accept(invokeOp);
409                                 }
410                             }
411                         }
412                     } else if (codeElement instanceof HATVectorBinaryOp hatVectorBinaryOp) {
413                         List<Value> inputOperandsInvoke = hatVectorBinaryOp.operands();
414                         for (Value inputOperand : inputOperandsInvoke) {
415                             if (inputOperand instanceof Op.Result r && r.op() instanceof CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
416                                 consumer.accept(varLoadOp);
417                             }
418                         }
419                     }
420                 });
421 
422         Set<CodeElement<?, ?>> nodesInvolved = vectorNodes.collect(Collectors.toSet());
423         if (nodesInvolved.isEmpty()) {
424             return funcOp;
425         }
426         funcOp = OpTk.transform(here, funcOp, (blockBuilder, op) -> {
427             if (!nodesInvolved.contains(op)) {
428                 blockBuilder.op(op);
429             } else if (op instanceof JavaOp.InvokeOp invokeOp) {
430                 insertVectorBinaryOp(blockBuilder, invokeOp, binaryOperation);
431             } else if (op instanceof CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
432                 insertVectorVarLoadOp(blockBuilder, varLoadOp);
433             }
434             return blockBuilder;
435         });
436         after(here, funcOp);
437         return funcOp;
438     }
439 
440     @Override
441     public CoreOp.FuncOp apply(CoreOp.FuncOp funcOp) {
442         switch (Objects.requireNonNull(vectorOperation)) {
443             case FLOAT4_LOAD -> funcOp = dialectifyVectorLoad(funcOp);
444             case FLOAT2_LOAD ->  funcOp = dialectifyVectorLoad(funcOp);
445             case OF -> funcOp = dialectifyVectorOf(funcOp);
446             case MAKE_MUTABLE -> funcOp = dialectifyMutableOf(funcOp);
447             default -> {
448                 // Find binary operations
449                 funcOp = dialectifyVectorBinaryOps(funcOp);
450                 funcOp = dialectifyVectorBinaryWithConcatenationOps(funcOp);
451             }
452         }
453         return funcOp;
454     }
455 
456     public static class AddPhase extends HATDialectifyVectorOpPhase {
457 
458         public AddPhase(Accelerator accelerator) {
459             super(accelerator, OpView.ADD);
460         }
461     }
462 
463     public static class DivPhase extends HATDialectifyVectorOpPhase {
464 
465         public DivPhase(Accelerator accelerator) {
466             super(accelerator, OpView.DIV);
467         }
468     }
469 
470     public static class MakeMutable extends HATDialectifyVectorOpPhase {
471 
472         public MakeMutable(Accelerator accelerator) {
473             super(accelerator, OpView.MAKE_MUTABLE);
474         }
475     }
476 
477     public static class Float4LoadPhase extends HATDialectifyVectorOpPhase {
478 
479         public Float4LoadPhase(Accelerator accelerator) {
480             super(accelerator, OpView.FLOAT4_LOAD);
481         }
482     }
483 
484     public static class Float2LoadPhase extends HATDialectifyVectorOpPhase {
485 
486         public Float2LoadPhase(Accelerator accelerator) {
487             super(accelerator, OpView.FLOAT2_LOAD);
488         }
489     }
490 
491     public static class Float4OfPhase extends HATDialectifyVectorOpPhase {
492 
493         public Float4OfPhase(Accelerator accelerator) {
494             super(accelerator, OpView.OF);
495         }
496     }
497 
498     public static class MulPhase extends HATDialectifyVectorOpPhase {
499 
500         public MulPhase(Accelerator accelerator) {
501             super(accelerator, OpView.MUL);
502         }
503     }
504 
505     public static class SubPhase extends HATDialectifyVectorOpPhase {
506 
507         public SubPhase(Accelerator accelerator) {
508             super(accelerator, OpView.SUB);
509         }
510     }
511 }