// = R1:0 u6 Not reached by d1 (covered collectively
// by d3 and d5), but following reached
// defs and uses from d1 will lead here.
- auto InPhiDefs = [&PhiDefs] (NodeAddr<DefNode*> DA) -> bool {
- return PhiDefs.count(DA.Id);
- };
for (auto UI = RealUses.begin(), UE = RealUses.end(); UI != UE; ) {
// For each reached register UI->first, there is a set UI->second, of
// uses of it. For each such use, check if it is reached by this phi,
// i.e. check if the set of its reaching uses intersects the set of
// this phi's defs.
- NodeRefSet &Uses = UI->second;
- for (auto I = Uses.begin(), E = Uses.end(); I != E; ) {
- auto UA = DFG.addr<UseNode*>(I->first);
+ NodeRefSet Uses = UI->second;
+ UI->second.clear();
+ for (std::pair<NodeId,LaneBitmask> I : Uses) {
+ auto UA = DFG.addr<UseNode*>(I.first);
// Undef flag is checked above.
assert((UA.Addr->getFlags() & NodeAttrs::Undef) == 0);
- RegisterRef R(UI->first, I->second);
- NodeList RDs = getAllReachingDefs(R, UA);
- // If none of the reaching defs of R are from this phi, remove this
- // use of R.
- I = any_of(RDs, InPhiDefs) ? std::next(I) : Uses.erase(I);
+ RegisterRef R(UI->first, I.second);
+ // Calculate the exposed part of the reached use.
+ RegisterAggr Covered(PRI);
+ for (NodeAddr<DefNode*> DA : getAllReachingDefs(R, UA)) {
+ if (PhiDefs.count(DA.Id))
+ break;
+ Covered.insert(DA.Addr->getRegRef(DFG));
+ }
+ if (RegisterRef RC = Covered.clearIn(R)) {
+ // We are updating the map for register UI->first, so we need
+ // to map RC to be expressed in terms of that register.
+ RegisterRef S = PRI.mapTo(RC, UI->first);
+ UI->second.insert({I.first, S.Mask});
+ }
}
- UI = Uses.empty() ? RealUses.erase(UI) : std::next(UI);
+ UI = UI->second.empty() ? RealUses.erase(UI) : std::next(UI);
}
// If this phi reaches some "real" uses, add it to the queue for upward
const RegisterAggr &DRs = PhiDRs.at(P.first);
if (!DRs.hasAliasOf(R))
continue;
- R = DRs.intersectWith(R);
+ R = PRI.mapTo(DRs.intersectWith(R), T.first);
for (std::pair<NodeId,LaneBitmask> V : T.second) {
LaneBitmask M = R.Mask & V.second;
if (M.none())
return false;
}
+RegisterRef PhysicalRegisterInfo::mapTo(RegisterRef RR, unsigned R) const {
+ if (RR.Reg == R)
+ return RR;
+ if (unsigned Idx = TRI.getSubRegIndex(R, RR.Reg))
+ return RegisterRef(R, TRI.composeSubRegIndexLaneMask(Idx, RR.Mask));
+ if (unsigned Idx = TRI.getSubRegIndex(RR.Reg, R)) {
+ const RegInfo &RI = RegInfos[R];
+ LaneBitmask RCM = RI.RegClass ? RI.RegClass->LaneMask
+ : LaneBitmask::getAll();
+ LaneBitmask M = TRI.reverseComposeSubRegIndexLaneMask(Idx, RR.Mask);
+ return RegisterRef(R, M & RCM);
+ }
+ llvm_unreachable("Invalid arguments: unrelated registers?");
+}
+
bool RegisterAggr::hasAliasOf(RegisterRef RR) const {
if (PhysicalRegisterInfo::isRegMaskId(RR.Reg))
--- /dev/null
+; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s
+
+; Check for sane output.
+; CHECK: vmpyweh
+
+target triple = "hexagon"
+
+declare i32 @llvm.hexagon.S2.clb(i32) #0
+declare i32 @llvm.hexagon.S2.asl.r.r(i32, i32) #0
+declare i32 @llvm.hexagon.S2.vrndpackwh(i64) #0
+declare i64 @llvm.hexagon.M2.mmpyl.s1(i64, i64) #0
+
+define i64 @fred(i32 %a0, i32 %a1) local_unnamed_addr #1 {
+b2:
+ br i1 undef, label %b15, label %b3
+
+b3: ; preds = %b2
+ %v4 = tail call i32 @llvm.hexagon.S2.clb(i32 %a1) #0
+ %v5 = add nsw i32 %v4, -32
+ %v6 = zext i32 %v5 to i64
+ %v7 = shl nuw i64 %v6, 32
+ %v8 = or i64 %v7, 0
+ %v9 = tail call i32 @llvm.hexagon.S2.asl.r.r(i32 %a0, i32 0)
+ %v10 = tail call i32 @llvm.hexagon.S2.vrndpackwh(i64 %v8)
+ %v11 = sext i32 %v9 to i64
+ %v12 = sext i32 %v10 to i64
+ %v13 = tail call i64 @llvm.hexagon.M2.mmpyl.s1(i64 %v11, i64 %v12)
+ %v14 = and i64 %v13, 4294967295
+ br label %b15
+
+b15: ; preds = %b3, %b2
+ %v16 = phi i64 [ %v14, %b3 ], [ 0, %b2 ]
+ %v17 = or i64 0, %v16
+ ret i64 %v17
+}
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind "target-cpu"="hexagonv55" }