From 1418f155d00c3fa2246a383e4dc881c2c484a23e Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 6 Oct 2016 16:18:04 +0000 Subject: [PATCH] [Hexagon] Avoid replacing full regs with subregisters in tied operands Doing so will result in the two-address pass generating incorrect code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283463 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonBitSimplify.cpp | 20 ++++++++++++++++++++ test/CodeGen/Hexagon/two-crash.ll | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 test/CodeGen/Hexagon/two-crash.ll diff --git a/lib/Target/Hexagon/HexagonBitSimplify.cpp b/lib/Target/Hexagon/HexagonBitSimplify.cpp index ea0c7345225..f8710f8f6fe 100644 --- a/lib/Target/Hexagon/HexagonBitSimplify.cpp +++ b/lib/Target/Hexagon/HexagonBitSimplify.cpp @@ -16,6 +16,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" @@ -23,6 +24,9 @@ using namespace llvm; +static cl::opt PreserveTiedOps("hexbit-keep-tied", cl::Hidden, + cl::init(true), cl::desc("Preserve subregisters in tied operands")); + namespace llvm { void initializeHexagonBitSimplifyPass(PassRegistry& Registry); FunctionPass *createHexagonBitSimplify(); @@ -187,6 +191,8 @@ namespace { MachineDominatorTree *MDT; bool visitBlock(MachineBasicBlock &B, Transformation &T, RegisterSet &AVs); + static bool hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI, + unsigned NewSub = Hexagon::NoSubRegister); }; char HexagonBitSimplify::ID = 0; @@ -328,6 +334,8 @@ bool HexagonBitSimplify::replaceRegWithSub(unsigned OldR, unsigned NewR, if (!TargetRegisterInfo::isVirtualRegister(OldR) || !TargetRegisterInfo::isVirtualRegister(NewR)) return false; + if (hasTiedUse(OldR, MRI, NewSR)) + return false; auto Begin = MRI.use_begin(OldR), End = MRI.use_end(); decltype(End) NextI; for (auto I = Begin; I != End; I = NextI) { @@ -344,6 +352,8 @@ bool HexagonBitSimplify::replaceSubWithSub(unsigned OldR, unsigned OldSR, if (!TargetRegisterInfo::isVirtualRegister(OldR) || !TargetRegisterInfo::isVirtualRegister(NewR)) return false; + if (OldSR != NewSR && hasTiedUse(OldR, MRI, NewSR)) + return false; auto Begin = MRI.use_begin(OldR), End = MRI.use_end(); decltype(End) NextI; for (auto I = Begin; I != End; I = NextI) { @@ -895,6 +905,16 @@ bool HexagonBitSimplify::isTransparentCopy(const BitTracker::RegisterRef &RD, } +bool HexagonBitSimplify::hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI, + unsigned NewSub) { + if (!PreserveTiedOps) + return false; + return any_of(MRI.use_operands(Reg), + [NewSub] (const MachineOperand &Op) -> bool { + return Op.getSubReg() != NewSub && Op.isTied(); + }); +} + // // Dead code elimination // diff --git a/test/CodeGen/Hexagon/two-crash.ll b/test/CodeGen/Hexagon/two-crash.ll new file mode 100644 index 00000000000..0ab02cda8a0 --- /dev/null +++ b/test/CodeGen/Hexagon/two-crash.ll @@ -0,0 +1,23 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s +; This testcase crashed, because we propagated a reg:sub into a tied use. +; The two-address pass rewrote it in a way that generated incorrect code. +; CHECK: r{{[0-9]+}} += lsr(r{{[0-9]+}}, #16) + +target triple = "hexagon" + +define i64 @fred(i64 %x) local_unnamed_addr #0 { +entry: + %t.sroa.0.0.extract.trunc = trunc i64 %x to i32 + %t4.sroa.4.0.extract.shift = lshr i64 %x, 16 + %add11 = add i32 0, %t.sroa.0.0.extract.trunc + %t14.sroa.3.0.extract.trunc = trunc i64 %t4.sroa.4.0.extract.shift to i32 + %t14.sroa.4.0.extract.shift = lshr i64 %x, 24 + %add21 = add i32 %add11, %t14.sroa.3.0.extract.trunc + %t24.sroa.3.0.extract.trunc = trunc i64 %t14.sroa.4.0.extract.shift to i32 + %add31 = add i32 %add21, %t24.sroa.3.0.extract.trunc + %conv32.mask = and i32 %add31, 255 + %conv33 = zext i32 %conv32.mask to i64 + ret i64 %conv33 +} + +attributes #0 = { norecurse nounwind readnone } -- 2.50.1