This is an archive of the discontinued LLVM Phabricator instance.

[IR] Add utility to convert constant expression operands (of an instruction) to instructions.
ClosedPublic

Authored by hsmhsm on Jun 3 2021, 6:28 PM.

Details

Summary

In the situation where we need to replace a constant operand C from a constant expression CE
by an instruction NI, it not possible without converting CE itself into an instruction. This
utility helps to convert the given set of constant expression operands from an instruction I
into a corresponding set of instructions.

The current use-case for this utility is from the patches - https://reviews.llvm.org/D103225
and https://reviews.llvm.org/D103655.

Diff Detail

Event Timeline

hsmhsm created this revision.Jun 3 2021, 6:28 PM
hsmhsm requested review of this revision.Jun 3 2021, 6:28 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 3 2021, 6:28 PM
hsmhsm retitled this revision from [IR] Add utility to convert constand expression operands (of an instruction) to instructions. to [IR] Add utility to convert constant expression operands (of an instruction) to instructions..
foad added a subscriber: foad.Jun 4 2021, 3:30 AM

Given a constant expression tree that contains CE, you are converting the entire tree to instructions. That is overkill. You only need to convert the nodes on the path from CE to the root.

rampitec added inline comments.Jun 4 2021, 1:08 PM
llvm/lib/IR/ReplaceConstant.cpp
145

This loop is just

append_range(Stack, CE3->operands());
rampitec added inline comments.Jun 4 2021, 1:25 PM
llvm/lib/IR/ReplaceConstant.cpp
108

The loop below can be replaced with the initializer:

SmallPtrSet<Value *, 4> Operands2(CE->op_begin(), CE->op_end());
rampitec added inline comments.Jun 4 2021, 2:37 PM
llvm/lib/IR/ReplaceConstant.cpp
107

To address Jay's comment I think you can pass an original CE into this function and amend the if to only execute it if CE != ReplacedCE. It will then skip the operands of the expression being replaced itself. I.e.:

@@ -77,12 +77,13 @@ void convertConstantExprsToInstructions(Instruction *I, ConstantExpr *CE,

   // Convert constant expressions operands of I (from the set CEOperands) to
   // instructions.
-  convertConstantExprsToInstructions(I, CEOperands, Insts);
+  convertConstantExprsToInstructions(I, CEOperands, Insts, CE);
 }

 void convertConstantExprsToInstructions(Instruction *I,
                                         SmallPtrSetImpl<Value *> &Operands,
-                                        SmallPtrSetImpl<Instruction *> &Insts) {
+                                        SmallPtrSetImpl<Instruction *> &Insts,
+                                        ConstantExpr *C) {
   for (Use &U : I->operands()) {
     auto *V = U.get();

@@ -104,11 +105,9 @@ void convertConstantExprsToInstructions(Instruction *I,
     I->replaceUsesOfWith(CE, NI);
     Insts.insert(NI);

-    if (CE->getNumOperands()) {
+    if (C != CE && CE->getNumOperands()) {
      SmallPtrSet<Value *, 4> Operands2;
      for (Use &UU : CE->operands())
        Operands2.insert(UU.get());
-      convertConstantExprsToInstructions(NI, Operands2, Insts);
+      convertConstantExprsToInstructions(NI, Operands2, Insts, C);
     }

     CE->removeDeadConstantUsers();

Note there are never recursive constant expressions.

rampitec added inline comments.Jun 4 2021, 2:47 PM
llvm/include/llvm/IR/ReplaceConstant.h
42

I would make Insts operand optional pointer. For instance I do not need it in D103655.

rampitec added inline comments.Jun 4 2021, 2:49 PM
llvm/lib/IR/ReplaceConstant.cpp
130

I think Visited is not needed. There can be no recursive CE.

hsmhsm added a comment.EditedJun 6 2021, 12:00 AM

Given a constant expression tree that contains CE, you are converting the entire tree to instructions. That is overkill. You only need to convert the nodes on the path from CE to the root.

Fixed it. Place take a look at latest submitted code.

llvm/lib/IR/ReplaceConstant.cpp
107

This will some extent reduces the unnecessary CE to I conversion. But, does not fully handle what @foad is suggesting. Consider below tree.

               I0
               |
              CE1
            /     \
         CE2      CE3
        /   \        \
     CE4    CE4      CE5
     /  \      \
  CE6   CE6    CE7
   /      \
CE8       CE9

Assuminng that, we need to convert CE4 into instructions, we only need to touch CEs in the two paths - (1) CE1, CE2, CE4 and (2) CE1, CE2, CE4. So result would be something like below.

I4_2 (CE7)
I4_1 (CE6, CE6)
I2 (I4_1, I4_2)
I1 (I2,  CE3)
I0 (I1)

But, the above code that you are suggesting here will convert every sub-tree except sub-trees starting from CE4.

Let's see what to do about it.

hsmhsm added a reviewer: foad.Jun 6 2021, 12:09 AM
hsmhsm updated this revision to Diff 350089.Jun 6 2021, 12:58 AM

Fixed few review comments by @rampitec.

hsmhsm marked 4 inline comments as done.Jun 6 2021, 12:59 AM
hsmhsm added inline comments.Jun 6 2021, 6:35 AM
llvm/lib/IR/ReplaceConstant.cpp
107

The above tree is incorrect, please read it as below.

          I0
          |
         CE1
       /     \
    CE2      CE3
   /   \        \
CE4    CE4      CE5
   \      \
   CE7    CE7

and the CE to I conversion as below:

I4 (CE7)
I2 (I4, I4)
I1 (I2,  CE3)
I0 (I1)
hsmhsm updated this revision to Diff 350099.Jun 6 2021, 6:47 AM

Make sure that only required constant expressions are converted into instructions.

hsmhsm marked an inline comment as done.Jun 6 2021, 6:50 AM
hsmhsm updated this revision to Diff 350177.Jun 6 2021, 11:15 PM

Replace llvm data structures by std c++ data structures, since passing complicated and nested
llvm data structures as a reference parameter of a function is very complicated.

hsmhsm updated this revision to Diff 350178.Jun 6 2021, 11:21 PM

Remove braces around single line IF statements.

rampitec accepted this revision.Jun 7 2021, 12:47 PM

Thanks! It makes it now I believe. D103655 has @timestwo() which exploits partial conversion change. LGTM.

This revision is now accepted and ready to land.Jun 7 2021, 12:47 PM
This revision was landed with ongoing or failed builds.Jun 7 2021, 2:53 PM
This revision was automatically updated to reflect the committed changes.