================
@@ -2479,6 +2479,39 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) {
       if (isBoolNot(previous))
         return previous.getInput();
 
+  // Fold constant unary operations.
+  if (auto srcConst = getInput().getDefiningOp<cir::ConstantOp>()) {
----------------
andykaylor wrote:

I implemented this change, and it looks much better for this PR, but I found 
that it leaves behind more dead constants when I use `createOrFold` during 
codegen. For instance, this:

```
short s = +(-3);
```

results in this before I explicitly delete the dead constants during 
canonicalization:
```
%19 = cir.const #cir.int<3> : !s32i
%20 = cir.const #cir.int<-3> : !s32i
%21 = cir.const #cir.int<-3> : !s32i
%22 = cir.const #cir.int<-3> : !s16i
cir.store align(2) %22, %1 : !s16i, !cir.ptr<!s16i>
```
This is because (1) we emit a constant 3 as the operand to the unary minus, (2) 
we fold the unary minus into a constant -3, (3) we fold the unary plus into 
another constant -3, and (4) we fold the implicit cast into the last constant 
-3. It all makes sense, but it was a bit shocking to see in the output.

My previous implementation did some of that, but it didn't introduce the 
duplicate constants in the cases where the folder is just returning the input 
value. If we return the actual input value, `createOrFold` will just use it, 
but if we return the attribute from the adaptor, it materializes a new 
constant. When the folder runs during the canonicalize pass, this isn't a 
problem because the folder doesn't materialize things in the middle of the 
process, but during codegen we materialize at each step.

I'm going to go with a hybrid approach where I look for the cases where we fold 
to the input value explicitly, and otherwise fold via the adaptor.

https://github.com/llvm/llvm-project/pull/174882
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to