[PATCH] Fixing inst-combine not to drops nsw when combining adds into mul (PR19263)

Jingyue Wu jingyue at google.com
Mon Jun 16 21:49:56 PDT 2014


Hi Dinesh, 

It looks pretty good overall. Thanks for working on this! Please find my comments inlined.

================
Comment at: lib/Transforms/InstCombine/InstructionCombining.cpp:445
@@ +444,3 @@
+
+  Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr;
+  Instruction::BinaryOps LHSOpcode = Instruction::BinaryOpsEnd;
----------------
I'd move these definitions closer to their uses. e.g.,
  Value *B = nullptr, *D = nullptr;
  Value *A = FactorBinaryOps(Op0, B, LHSOpcode);

================
Comment at: lib/Transforms/InstCombine/InstructionCombining.cpp:452
@@ -408,3 +451,3 @@
 
-  // Factorization.
-  if (Op0 && Op1 && Op0->getOpcode() == Op1->getOpcode()) {
+  A = FactorBinaryOps(Op0, B, LHSOpcode);
+  C = FactorBinaryOps(Op1, D, RHSOpcode);
----------------
Correct me if I'm wrong. I think the current logic seems unable to convert
  %z = mul nsw i32 %x, %y
  %z3 = mul nsw i32 %z, 3
  %z4 = add nsw i32 %z, %z3
to
  %z = mul nsw i32 %x, %y
  %z4 = mul nsw i32 %z, 4
because if %z is in the format of %x * %y, you will not try the identity factorization (i.e., %z * 1). 

If it is indeed a missed opportunity, it may not be too difficult to cover. For example, we can try all four combinations:
# LHS (binary op), RHS (binary op)
# LHS (identity), RHS (binary op)
# LHS (binary op), RHS (identity)
# LHS (identity), RHS (identity) // probably already handled somewhere else?

Anyway, we can do this later. 

================
Comment at: lib/Transforms/InstCombine/InstructionCombining.cpp:466
@@ +465,3 @@
+      bool InnerCommutative = Instruction::isCommutative(LHSOpcode);
+      // Does "X op' (Y op Z)" always equal "(X op' Y) op (X op' Z)"?
+      if (LeftDistributesOverRight(LHSOpcode, TopLevelOpcode))
----------------
I feel the logic of this IF and next IF (if (RightDistributesOverLeft) a bit difficult to follow. There is also some copy and paste. What about extracting the check on InnerCommutative out? Something like:
```
try(a, b, c, d);
if (op' is commutative) {
  try(b, a, c, d);
  try(a, b, d, c);
  try(b, a, c, d);
}
```
By doing this, inside each "try", we don't need to think about whether op' is commutative. 

What do you think?

http://reviews.llvm.org/D3799






More information about the llvm-commits mailing list