[Hexagon] Account for negative offset when limiting max deviation
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Wed, 25 Oct 2017 18:46:40 +0000 (18:46 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Wed, 25 Oct 2017 18:46:40 +0000 (18:46 +0000)
In getOffsetRange, Max can be set to 0 to force the extender replacement
to be at or below the original value. This would cause the new offset to
be non-negative, which is preferred for memory instructions (to reduce
the likelihood of it getting constant-extended due to predication). The
problem happens when the range is shifted by an offset (present in the
instruction being examined) and the offset is negative. The entire range
for the allowable deviation will then be strictly negative. This creates
a problem, since 0 is assumed to be a valid deviation.

llvm-svn: 316601

llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp
llvm/test/CodeGen/Hexagon/cext-opt-range-offset.mir [new file with mode: 0644]

index 5b72fea..40e1145 100644 (file)
@@ -1040,10 +1040,13 @@ OffsetRange HCE::getOffsetRange(Register Rb, const MachineInstr &MI) const {
   unsigned L = Log2_32(A);
   unsigned S = 10+L;  // sint11_L
   int32_t Min = -alignDown((1<<S)-1, A);
-  int32_t Max = 0;  // Force non-negative offsets.
 
-  OffsetRange R = { Min, Max, A };
+  // The range will be shifted by Off. To prefer non-negative offsets,
+  // adjust Max accordingly.
   int32_t Off = MI.getOperand(OffP).getImm();
+  int32_t Max = Off >= 0 ? 0 : -Off;
+
+  OffsetRange R = { Min, Max, A };
   return R.shift(Off);
 }
 
@@ -1622,6 +1625,9 @@ bool HCE::replaceInstrExpr(const ExtDesc &ED, const ExtenderInit &ExtI,
 #ifndef NDEBUG
     // Make sure the output is within allowable range for uses.
     OffsetRange Uses = getOffsetRange(MI.getOperand(0));
+    if (!Uses.contains(Diff))
+      dbgs() << "Diff: " << Diff << " out of range " << Uses
+             << " for " << MI;
     assert(Uses.contains(Diff));
 #endif
     MBB.erase(MI);
diff --git a/llvm/test/CodeGen/Hexagon/cext-opt-range-offset.mir b/llvm/test/CodeGen/Hexagon/cext-opt-range-offset.mir
new file mode 100644 (file)
index 0000000..6fb5348
--- /dev/null
@@ -0,0 +1,43 @@
+# RUN: llc -march=hexagon -run-pass hexagon-cext-opt %s -o - | FileCheck %s
+
+# Check that this testcase does not crash.
+# CHECK: L4_and_memopw_io
+
+---
+name: fred
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: intregs }
+  - { id: 1, class: intregs }
+  - { id: 2, class: intregs }
+  - { id: 3, class: intregs }
+  - { id: 4, class: predregs }
+  - { id: 5, class: intregs }
+  - { id: 6, class: intregs }
+body: |
+  bb.0:
+    successors: %bb.1
+        %0 = A2_tfrsi -360184608
+        %1 = L2_loadri_io %0, -1024
+
+  bb.1:
+    successors: %bb.2
+        %2 = A2_tfrsi -234944641
+        %3 = A2_tfrsi -360185632
+        L4_and_memopw_io %3, 0, %2
+
+  bb.2:
+    successors: %bb.3, %bb.4
+        %4 = IMPLICIT_DEF
+        J2_jumpt %4, %bb.4, implicit-def %pc
+        J2_jump %bb.3, implicit-def %pc
+
+  bb.3:
+    successors: %bb.4
+
+  bb.4:
+    successors: %bb.4
+        %5 = A2_tfrsi -234944521
+        %6 = A2_tfrsi -360185632
+        L4_and_memopw_io %6, 0, %5
+...