[PATCH] D97050: [LoopInfo] Look through trunc instructions

Sjoerd Meijer via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 19 07:35:55 PST 2021


SjoerdMeijer created this revision.
SjoerdMeijer added reviewers: fhahn, dmgreen, wmi, kazu.
Herald added a subscriber: hiraditya.
SjoerdMeijer requested review of this revision.
Herald added a project: LLVM.

In trying to get the induction variable with `getInductionVariable`, a compare instruction of this form is pattern matched:

  cmp = IndVar < FinalValue

But IndVarSimplify could be responsible for generating a slightly different pattern:

  cmp = Trunc(IndVar) < FinalValue

This looks through the trunc instructions so that we try to pattern match the original pattern.

This depends on D89693 <https://reviews.llvm.org/D89693>. `getInductionVariable` is used by `getInductionDescriptor` which is used in TTI hook getPreferredAddressingMode. With this change, it can now find an IV for this loop, and it generates post-increments.


https://reviews.llvm.org/D97050

Files:
  llvm/lib/Analysis/LoopInfo.cpp
  llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll


Index: llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll
===================================================================
--- llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll
+++ llvm/test/CodeGen/AArch64/arm64-scaled_iv.ll
@@ -13,27 +13,23 @@
 define void @mulDouble(double* nocapture %a, double* nocapture %b, double* nocapture %c) {
 ; CHECK-LABEL: @mulDouble(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[B8:%.*]] = bitcast double* [[B:%.*]] to i8*
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr double, double* [[A:%.*]], i64 1
-; CHECK-NEXT:    [[SCEVGEP1:%.*]] = bitcast double* [[SCEVGEP]] to i8*
-; CHECK-NEXT:    [[SCEVGEP4:%.*]] = getelementptr double, double* [[C:%.*]], i64 2
-; CHECK-NEXT:    [[SCEVGEP45:%.*]] = bitcast double* [[SCEVGEP4]] to i8*
+; CHECK-NEXT:    [[SCEVGEP3:%.*]] = getelementptr double, double* [[C:%.*]], i64 2
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[UGLYGEP9:%.*]] = getelementptr i8, i8* [[B8]], i64 [[LSR_IV]]
-; CHECK-NEXT:    [[UGLYGEP910:%.*]] = bitcast i8* [[UGLYGEP9]] to double*
-; CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[UGLYGEP910]], align 8
-; CHECK-NEXT:    [[UGLYGEP6:%.*]] = getelementptr i8, i8* [[SCEVGEP45]], i64 [[LSR_IV]]
-; CHECK-NEXT:    [[UGLYGEP67:%.*]] = bitcast i8* [[UGLYGEP6]] to double*
-; CHECK-NEXT:    [[TMP2:%.*]] = load double, double* [[UGLYGEP67]], align 8
+; CHECK-NEXT:    [[LSR_IV6:%.*]] = phi double* [ [[SCEVGEP7:%.*]], [[FOR_BODY]] ], [ [[B:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[LSR_IV4:%.*]] = phi double* [ [[SCEVGEP5:%.*]], [[FOR_BODY]] ], [ [[SCEVGEP3]], [[ENTRY]] ]
+; CHECK-NEXT:    [[LSR_IV2:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 19, [[ENTRY]] ]
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi double* [ [[SCEVGEP1:%.*]], [[FOR_BODY]] ], [ [[SCEVGEP]], [[ENTRY]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[LSR_IV6]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load double, double* [[LSR_IV4]], align 8
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[TMP1]], [[TMP2]]
-; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, i8* [[SCEVGEP1]], i64 [[LSR_IV]]
-; CHECK-NEXT:    [[UGLYGEP2:%.*]] = bitcast i8* [[UGLYGEP]] to double*
-; CHECK-NEXT:    store double [[MUL]], double* [[UGLYGEP2]], align 8
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nuw nsw i64 [[LSR_IV]], 8
-; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[LSR_IV_NEXT]] to i32
-; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[TMP3]], 152
+; CHECK-NEXT:    store double [[MUL]], double* [[LSR_IV]], align 8
+; CHECK-NEXT:    [[SCEVGEP1]] = getelementptr double, double* [[LSR_IV]], i64 1
+; CHECK-NEXT:    [[LSR_IV_NEXT]] = add nsw i32 [[LSR_IV2]], -1
+; CHECK-NEXT:    [[SCEVGEP5]] = getelementptr double, double* [[LSR_IV4]], i64 1
+; CHECK-NEXT:    [[SCEVGEP7]] = getelementptr double, double* [[LSR_IV6]], i64 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[LSR_IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
 ; CHECK:       for.end:
 ; CHECK-NEXT:    ret void
Index: llvm/lib/Analysis/LoopInfo.cpp
===================================================================
--- llvm/lib/Analysis/LoopInfo.cpp
+++ llvm/lib/Analysis/LoopInfo.cpp
@@ -303,6 +303,16 @@
   Instruction *LatchCmpOp0 = dyn_cast<Instruction>(CmpInst->getOperand(0));
   Instruction *LatchCmpOp1 = dyn_cast<Instruction>(CmpInst->getOperand(1));
 
+  // IndVarSimplify can introduce truncs after certain induction variable
+  // optimisations so that the cmp instructions looks like:
+  //
+  //     cmp = Trunc(IndVar) < FinalValue
+  //
+  // Here we look through the Trunc instruction to see if we can still match
+  // instruction IndVar.
+  if (isa<TruncInst>(LatchCmpOp0))
+    LatchCmpOp0 = dyn_cast<Instruction>(LatchCmpOp0->getOperand(0));
+
   for (PHINode &IndVar : Header->phis()) {
     InductionDescriptor IndDesc;
     if (!InductionDescriptor::isInductionPHI(&IndVar, this, &SE, IndDesc))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D97050.324976.patch
Type: text/x-patch
Size: 4050 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210219/aa5adbb0/attachment.bin>


More information about the llvm-commits mailing list