[PATCH] D125248: [instcombine] Propagate freeze back to def

Mircea Trofin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 9 11:09:26 PDT 2022


mtrofin created this revision.
mtrofin added reviewers: hyeongyukim, nikic, lebedev.ri.
Herald added a subscriber: hiraditya.
Herald added a project: All.
mtrofin requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

We noticed a regression in
llvm-test-suite/MicroBenchmarks/ImageProcessing/Interpolation that,
through bisection, appeared to be caused by D124252 <https://reviews.llvm.org/D124252>. Upon investigation,
the root cause appears to be the way D105392 <https://reviews.llvm.org/D105392> propagates upwards freezes.

D124252 <https://reviews.llvm.org/D124252> would freeze the `cmp` result, and loop unswitching would
otherwise happen identically. We'd then do instcombine. At this point,
we'd be presented with a few redundant definitions - see the `%idx1` and
`%idx2` in the added test. They'd have uses in the `then` and `else`
sides of the unswitched loop that, before D124252 <https://reviews.llvm.org/D124252>, would be recognized
as equivalent and optimized out (the test glosses over that and just
uses the `mock_use` function to make sure the values have a use).

D124252 <https://reviews.llvm.org/D124252>'s introduction of the `freeze` kicked in the behavior introduced
by D105392 <https://reviews.llvm.org/D105392>. The problem is that the freeze would be always propagated up
right before the current freeze - which in our case would leave one of
the equivalent `idx` before the freeze and one after. The two would be
now different, and we lose the optimization opportunity. Here's what the
IR looked like post-instcombine, for the newly added test:

  define i1 @func(i32 %0, i32 noundef %1) {
    %dr = lshr i32 %0, 2
    %idx1 = zext i32 %dr to i64
    %dr.fr = freeze i32 %dr
    %add = add i32 %dr.fr, 1
    %cmp = icmp slt i32 %add, %1
    %idx2 = zext i32 %dr.fr to i64
    %v = call i1 @use(i64 %idx1, i64 %idx2)
    %ret = and i1 %v, %cmp
    ret i1 %ret
  }

Note how `%idx1` and `%idx2` are using, one the pre-freeze def of `%dr`
and one the post-freeze (i.e. `%dr.fr`).

This patch moves the freeze right after definition.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125248

Files:
  llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
  llvm/test/Transforms/InstCombine/freeze.ll


Index: llvm/test/Transforms/InstCombine/freeze.ll
===================================================================
--- llvm/test/Transforms/InstCombine/freeze.ll
+++ llvm/test/Transforms/InstCombine/freeze.ll
@@ -594,5 +594,26 @@
   ret void
 }
 
-
-
+declare i1 @mock_use(i64, i64)
+define i1 @propagate_freeze(i32 %0, i32 noundef %1) {
+; CHECK-LABEL: @propagate_freeze(
+; CHECK-NEXT:    [[DOTFR:%.*]] = freeze i32 [[TMP0:%.*]]
+; CHECK-NEXT:    [[DR:%.*]] = lshr i32 [[DOTFR]], 2
+; CHECK-NEXT:    [[IDX1:%.*]] = zext i32 [[DR]] to i64
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[DR]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[ADD]], [[TMP1:%.*]]
+; CHECK-NEXT:    [[IDX2:%.*]] = zext i32 [[DR]] to i64
+; CHECK-NEXT:    [[V:%.*]] = call i1 @mock_use(i64 [[IDX1]], i64 [[IDX2]])
+; CHECK-NEXT:    [[RET:%.*]] = and i1 [[V]], [[CMP]]
+; CHECK-NEXT:    ret i1 [[RET]]
+;
+  %dr = lshr i32 %0, 2
+  %idx1 = zext i32 %dr to i64
+  %add = add i32 %dr, 1
+  %cmp = icmp slt i32 %add, %1
+  %cmp.fr = freeze i1 %cmp
+  %idx2 = zext i32 %dr to i64
+  %v = call i1 @mock_use(i64 %idx1, i64 %idx2)
+  %ret = and i1 %v, %cmp.fr
+  ret i1 %ret
+}
Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -3801,9 +3801,17 @@
 
   auto *FrozenMaybePoisonOperand = new FreezeInst(
       MaybePoisonOperand->get(), MaybePoisonOperand->get()->getName() + ".fr");
-
+  auto *IP = dyn_cast<Instruction>(MaybePoisonOperand->get());
   replaceUse(*MaybePoisonOperand, FrozenMaybePoisonOperand);
-  FrozenMaybePoisonOperand->insertBefore(OrigOpInst);
+  if (IP) {
+    if (isa<PHINode>(IP))
+      IP->getParent()->getInstList().insert(
+          IP->getParent()->getFirstInsertionPt(), FrozenMaybePoisonOperand);
+    else
+      FrozenMaybePoisonOperand->insertAfter(IP);
+  } else {
+    FrozenMaybePoisonOperand->insertBefore(OrigOpInst);
+  }
   return OrigOp;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D125248.428134.patch
Type: text/x-patch
Size: 2072 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220509/ac65d2b5/attachment.bin>


More information about the llvm-commits mailing list