[Hexagon] Generate trap/undef if misaligned access is detected
authorKrzysztof Parzyszek <kparzysz@quicinc.com>
Fri, 25 Jun 2021 14:30:59 +0000 (09:30 -0500)
committerKrzysztof Parzyszek <kparzysz@quicinc.com>
Tue, 6 Jul 2021 19:52:23 +0000 (14:52 -0500)
This applies to memory accesses to (compile-time) constant addresses
(such as memory-mapped registers). Currently when a misaligned access
to such an address is detected, a fatal error is reported. This change
will emit a remark, and the compilation will continue with a trap,
and "undef" (for loads) emitted.

This fixes https://llvm.org/PR50838.

Differential Revision: https://reviews.llvm.org/D50524

llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
llvm/lib/Target/Hexagon/HexagonISelLowering.h
llvm/test/CodeGen/Hexagon/misaligned-const-load.ll
llvm/test/CodeGen/Hexagon/misaligned-const-store.ll

index 06fee76..6ded323 100644 (file)
@@ -35,6 +35,8 @@
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/InlineAsm.h"
@@ -1912,25 +1914,57 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
   return nullptr;
 }
 
-void
+bool
 HexagonTargetLowering::validateConstPtrAlignment(SDValue Ptr, Align NeedAlign,
-      const SDLoc &dl) const {
+      const SDLoc &dl, SelectionDAG &DAG) const {
   auto *CA = dyn_cast<ConstantSDNode>(Ptr);
   if (!CA)
-    return;
+    return true;
   unsigned Addr = CA->getZExtValue();
   Align HaveAlign =
       Addr != 0 ? Align(1ull << countTrailingZeros(Addr)) : NeedAlign;
-  if (HaveAlign < NeedAlign) {
-    std::string ErrMsg;
-    raw_string_ostream O(ErrMsg);
-    O << "Misaligned constant address: " << format_hex(Addr, 10)
-      << " has alignment " << HaveAlign.value()
-      << ", but the memory access requires " << NeedAlign.value();
-    if (DebugLoc DL = dl.getDebugLoc())
-      DL.print(O << ", at ");
-    report_fatal_error(O.str());
-  }
+  if (HaveAlign >= NeedAlign)
+    return true;
+
+  static int DK_MisalignedTrap = llvm::getNextAvailablePluginDiagnosticKind();
+
+  struct DiagnosticInfoMisalignedTrap : public DiagnosticInfo {
+    DiagnosticInfoMisalignedTrap(StringRef M)
+      : DiagnosticInfo(DK_MisalignedTrap, DS_Remark), Msg(M) {}
+    void print(DiagnosticPrinter &DP) const override {
+      DP << Msg;
+    }
+    static bool classof(const DiagnosticInfo *DI) {
+      return DI->getKind() == DK_MisalignedTrap;
+    }
+    StringRef Msg;
+  };
+
+  std::string ErrMsg;
+  raw_string_ostream O(ErrMsg);
+  O << "Misaligned constant address: " << format_hex(Addr, 10)
+    << " has alignment " << HaveAlign.value()
+    << ", but the memory access requires " << NeedAlign.value();
+  if (DebugLoc DL = dl.getDebugLoc())
+    DL.print(O << ", at ");
+  O << ". The instruction has been replaced with a trap.";
+
+  DAG.getContext()->diagnose(DiagnosticInfoMisalignedTrap(O.str()));
+  return false;
+}
+
+SDValue
+HexagonTargetLowering::replaceMemWithUndef(SDValue Op, SelectionDAG &DAG)
+      const {
+  const SDLoc &dl(Op);
+  auto *LS = cast<LSBaseSDNode>(Op.getNode());
+  assert(!LS->isIndexed() && "Not expecting indexed ops on constant address");
+
+  SDValue Chain = LS->getChain();
+  SDValue Trap = DAG.getNode(ISD::TRAP, dl, MVT::Other, Chain);
+  if (LS->getOpcode() == ISD::LOAD)
+    return DAG.getMergeValues({DAG.getUNDEF(ty(Op)), Trap}, dl);
+  return Trap;
 }
 
 // Bit-reverse Load Intrinsic: Check if the instruction is a bit reverse load
@@ -2902,7 +2936,9 @@ HexagonTargetLowering::LowerLoad(SDValue Op, SelectionDAG &DAG) const {
   }
 
   Align ClaimAlign = LN->getAlign();
-  validateConstPtrAlignment(LN->getBasePtr(), ClaimAlign, dl);
+  if (!validateConstPtrAlignment(LN->getBasePtr(), ClaimAlign, dl, DAG))
+    return replaceMemWithUndef(Op, DAG);
+
   // Call LowerUnalignedLoad for all loads, it recognizes loads that
   // don't need extra aligning.
   SDValue LU = LowerUnalignedLoad(SDValue(LN, 0), DAG);
@@ -2934,7 +2970,8 @@ HexagonTargetLowering::LowerStore(SDValue Op, SelectionDAG &DAG) const {
   }
 
   Align ClaimAlign = SN->getAlign();
-  validateConstPtrAlignment(SN->getBasePtr(), ClaimAlign, dl);
+  if (!validateConstPtrAlignment(SN->getBasePtr(), ClaimAlign, dl, DAG))
+    return replaceMemWithUndef(Op, DAG);
 
   MVT StoreTy = SN->getMemoryVT().getSimpleVT();
   Align NeedAlign = Subtarget.getTypeAlignment(StoreTy);
index 7d376f9..d518c03 100644 (file)
@@ -341,8 +341,9 @@ private:
   void initializeHVXLowering();
   unsigned getPreferredHvxVectorAction(MVT VecTy) const;
 
-  void validateConstPtrAlignment(SDValue Ptr, Align NeedAlign,
-                                 const SDLoc &dl) const;
+  bool validateConstPtrAlignment(SDValue Ptr, Align NeedAlign, const SDLoc &dl,
+                                 SelectionDAG &DAG) const;
+  SDValue replaceMemWithUndef(SDValue Op, SelectionDAG &DAG) const;
 
   std::pair<SDValue,int> getBaseAndOffset(SDValue Addr) const;
 
index 74b7443..f209d80 100644 (file)
@@ -1,7 +1,7 @@
-; RUN: not --crash llc -march=hexagon < %s 2>&1 | FileCheck %s
+; RUN: llc -march=hexagon < %s 2>&1 | FileCheck %s
 
 ; Check that the misaligned load is diagnosed.
-; CHECK: LLVM ERROR: Misaligned constant address: 0x00012345 has alignment 1, but the memory access requires 4, at misaligned-const-load.c:2:10
+; CHECK: remark: Misaligned constant address: 0x00012345 has alignment 1, but the memory access requires 4, at misaligned-const-load.c:2:10. The instruction has been replaced with a trap.
 
 target triple = "hexagon"
 
index 0a5b1aa..27f472e 100644 (file)
@@ -1,7 +1,7 @@
-; RUN: not --crash llc -march=hexagon < %s 2>&1 | FileCheck %s
+; RUN: llc -march=hexagon < %s 2>&1 | FileCheck %s
 
 ; Check that the misaligned store is diagnosed.
-; CHECK: LLVM ERROR: Misaligned constant address: 0x00012345 has alignment 1, but the memory access requires 4, at misaligned-const-store.c:2:10
+; CHECK: remark: Misaligned constant address: 0x00012345 has alignment 1, but the memory access requires 4, at misaligned-const-store.c:2:10. The instruction has been replaced with a trap.
 
 target triple = "hexagon"