Skip to content

[RISCV] Teach expandRV32ZdinxStore to handle memoperand not being present. #113981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 29, 2024

Conversation

topperc
Copy link
Collaborator

@topperc topperc commented Oct 28, 2024

I received a report that the outliner drops memoperands and causes this code to crash. Handle this by only copying the memoperand if it exists.

Similar for expandRV32ZdinxLoad

…sent.

I received a report that the outliner drops memoperands and causes
this code to crash. Handle this by only copying the memoperand if it
exists.
@llvmbot
Copy link
Member

llvmbot commented Oct 28, 2024

@llvm/pr-subscribers-backend-risc-v

Author: Craig Topper (topperc)

Changes

I received a report that the outliner drops memoperands and causes this code to crash. Handle this by only copying the memoperand if it exists.

Similar for expandRV32ZdinxLoad


Full diff: https://github.com/llvm/llvm-project/pull/113981.diff

1 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (+47-42)
diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index 5dcec078856ead..eb3e1a1fe9fd5e 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -320,34 +320,37 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB,
   Register Hi =
       TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);
 
-  assert(MBBI->hasOneMemOperand() && "Expected mem operand");
-  MachineMemOperand *OldMMO = MBBI->memoperands().front();
-  MachineFunction *MF = MBB.getParent();
-  MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);
-  MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);
-
-  BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
-      .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill()))
-      .addReg(MBBI->getOperand(1).getReg())
-      .add(MBBI->getOperand(2))
-      .setMemRefs(MMOLo);
+  auto MIBLo = BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
+                   .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill()))
+                   .addReg(MBBI->getOperand(1).getReg())
+                   .add(MBBI->getOperand(2));
 
+  MachineInstrBuilder MIBHi;
   if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
     assert(MBBI->getOperand(2).getOffset() % 8 == 0);
     MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);
-    BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
-        .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
-        .add(MBBI->getOperand(1))
-        .add(MBBI->getOperand(2))
-        .setMemRefs(MMOHi);
+    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
+                .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
+                .add(MBBI->getOperand(1))
+                .add(MBBI->getOperand(2));
   } else {
     assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));
-    BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
-        .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
-        .add(MBBI->getOperand(1))
-        .addImm(MBBI->getOperand(2).getImm() + 4)
-        .setMemRefs(MMOHi);
+    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
+                .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
+                .add(MBBI->getOperand(1))
+                .addImm(MBBI->getOperand(2).getImm() + 4);
+  }
+
+  if (!MBBI->memoperands_empty()) {
+    assert(MBBI->hasOneMemOperand() && "Expected mem operand");
+    MachineMemOperand *OldMMO = MBBI->memoperands().front();
+    MachineFunction *MF = MBB.getParent();
+    MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);
+    MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);
+    MIBLo.setMemRefs(MMOLo);
+    MIBHi.setMemRefs(MMOHi);
   }
+
   MBBI->eraseFromParent();
   return true;
 }
@@ -364,46 +367,48 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,
   Register Hi =
       TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);
 
-  assert(MBBI->hasOneMemOperand() && "Expected mem operand");
-  MachineMemOperand *OldMMO = MBBI->memoperands().front();
-  MachineFunction *MF = MBB.getParent();
-  MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);
-  MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);
+  MachineInstrBuilder MIBLo, MIBHi;
 
   // If the register of operand 1 is equal to the Lo register, then swap the
   // order of loading the Lo and Hi statements.
   bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg();
   // Order: Lo, Hi
   if (!IsOp1EqualToLo) {
-    BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
-        .addReg(MBBI->getOperand(1).getReg())
-        .add(MBBI->getOperand(2))
-        .setMemRefs(MMOLo);
+    MIBLo = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
+                .addReg(MBBI->getOperand(1).getReg())
+                .add(MBBI->getOperand(2));
   }
 
   if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
     auto Offset = MBBI->getOperand(2).getOffset();
     assert(Offset % 8 == 0);
     MBBI->getOperand(2).setOffset(Offset + 4);
-    BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
-        .addReg(MBBI->getOperand(1).getReg())
-        .add(MBBI->getOperand(2))
-        .setMemRefs(MMOHi);
+    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
+                .addReg(MBBI->getOperand(1).getReg())
+                .add(MBBI->getOperand(2));
     MBBI->getOperand(2).setOffset(Offset);
   } else {
     assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));
-    BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
-        .addReg(MBBI->getOperand(1).getReg())
-        .addImm(MBBI->getOperand(2).getImm() + 4)
-        .setMemRefs(MMOHi);
+    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
+                .addReg(MBBI->getOperand(1).getReg())
+                .addImm(MBBI->getOperand(2).getImm() + 4);
   }
 
   // Order: Hi, Lo
   if (IsOp1EqualToLo) {
-    BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
-        .addReg(MBBI->getOperand(1).getReg())
-        .add(MBBI->getOperand(2))
-        .setMemRefs(MMOLo);
+    MIBLo = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
+                .addReg(MBBI->getOperand(1).getReg())
+                .add(MBBI->getOperand(2));
+  }
+
+  if (!MBBI->memoperands_empty()) {
+    assert(MBBI->hasOneMemOperand() && "Expected mem operand");
+    MachineMemOperand *OldMMO = MBBI->memoperands().front();
+    MachineFunction *MF = MBB.getParent();
+    MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);
+    MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);
+    MIBLo.setMemRefs(MMOLo);
+    MIBHi.setMemRefs(MMOHi);
   }
 
   MBBI->eraseFromParent();

Copy link
Contributor

@wangpc-pp wangpc-pp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@topperc topperc merged commit 3f4468f into llvm:main Oct 29, 2024
10 checks passed
@topperc topperc deleted the pr/zdinxpair-memop branch October 29, 2024 05:37
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
…sent. (llvm#113981)

I received a report that the outliner drops memoperands and causes this
code to crash. Handle this by only copying the memoperand if it exists.

Similar for expandRV32ZdinxLoad
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Dec 4, 2024
…a0708702b

Local branch amd-gfx 4eaa070 Merged main:a4fd3dba6e285734bc635b0651a30dfeffedeada into amd-gfx:7dad81725749
Remote branch main 3f4468f [RISCV] Teach expandRV32ZdinxStore to handle memoperand not being present. (llvm#113981)

Change-Id: I5de1c2e581441dbfb97e34c12805499a88c6bc68
@futog
Copy link
Contributor

futog commented Jan 24, 2025

Hi Craig,

the issue is still there with the following MIR:
PseudoRV32ZdinxSD killed renamable $x10_x11, killed renamable $x12, 8 :: (store (s64) into %ir.arrayidx13, !tbaa !6), (store (s64) into %ir.arrayidx20, !tbaa !6)
Assertion: assert(MBBI->hasOneMemOperand() && "Expected mem operand");

Regards,
Gergely

@topperc
Copy link
Collaborator Author

topperc commented Jan 24, 2025

Hi Craig,

the issue is still there with the following MIR: PseudoRV32ZdinxSD killed renamable $x10_x11, killed renamable $x12, 8 :: (store (s64) into %ir.arrayidx13, !tbaa !6), (store (s64) into %ir.arrayidx20, !tbaa !6) Assertion: assert(MBBI->hasOneMemOperand() && "Expected mem operand");

Regards, Gergely

Do you have test that generates that MIR? I'm not sure where in the code 2 operands can be created.

@futog
Copy link
Contributor

futog commented Jan 27, 2025

Hi,

Sorry for the late answer, I created a reduced test: https://godbolt.org/z/sPs4E16x6

Regards, Gergely

This is the relevant part:

*** MachineFunction at end of ISel ***
# Machine code for function __rem_pio2: IsSSA, TracksLiveness
Frame Objects:
  fi#-2: size=4, align=4, fixed, at location [SP+4]
  fi#-1: size=4, align=16, fixed, at location [SP]
Function Live Ins: $x17 in %7

bb.0.entry:
  successors: %bb.3(0x40000000), %bb.2(0x40000000); %bb.3(50.00%), %bb.2(50.00%)
  liveins: $x17
  %7:gpr = COPY $x17
  %10:gpr = ANDI %7:gpr, 1
  %9:gprnox0 = LW %fixed-stack.0, 0 :: (load (s32) from %fixed-stack.0)
  %8:gprnox0 = LW %fixed-stack.1, 0 :: (load (s32) from %fixed-stack.1, align 16)
  BNE killed %10:gpr, $x0, %bb.3
  PseudoBR %bb.2

bb.1.common.ret:
; predecessors: %bb.2, %bb.3

  %13:gpr = COPY $x0
  $x10 = COPY %13:gpr
  PseudoRET implicit $x10

bb.2.if.then7:
; predecessors: %bb.0
  successors: %bb.1(0x80000000); %bb.1(100.00%)

  %11:gprpair = FCVT_D_W_IN32X $x0, 0
  PseudoRV32ZdinxSD killed %11:gprpair, %8:gprnox0, 0 :: (store (s64) into %ir.arrayidx13)
  PseudoBR %bb.1

bb.3.if.else:
; predecessors: %bb.0
  successors: %bb.1(0x80000000); %bb.1(100.00%)

  %12:gprpair = FCVT_D_W_IN32X $x0, 0
  PseudoRV32ZdinxSD killed %12:gprpair, %9:gprnox0, 0 :: (store (s64) into %ir.arrayidx20)
  PseudoBR %bb.1

# End machine code for function __rem_pio2.

# *** IR Dump After Tail Duplication (tailduplication) ***:
# Machine code for function __rem_pio2: NoPHIs, TracksLiveness, NoVRegs, TiedOpsRewritten, TracksDebugUserValues
Frame Objects:
  fi#-2: size=4, align=4, fixed, at location [SP+4]
  fi#-1: size=4, align=16, fixed, at location [SP]
Function Live Ins: $x17

bb.0.entry:
  successors: %bb.3(0x40000000), %bb.1(0x40000000); %bb.3(50.00%), %bb.1(50.00%)
  liveins: $x17
  renamable $x10 = ANDI killed renamable $x17, 1
  BNE killed renamable $x10, $x0, %bb.3

bb.1.if.then7:
; predecessors: %bb.0
  successors: %bb.2(0x80000000); %bb.2(100.00%)

  renamable $x10 = LW $x2, 0 :: (load (s32) from %fixed-stack.1, align 16)

bb.2.common.ret:
; predecessors: %bb.1, %bb.3
  liveins: $x10
  renamable $x12_x13 = FCVT_D_W_IN32X $x0, 0
  PseudoRV32ZdinxSD killed renamable $x12_x13, killed renamable $x10, 0 :: (store (s64) into %ir.arrayidx13), (store (s64) into %ir.arrayidx20)
  $x10 = COPY $x0
  PseudoRET implicit $x10

bb.3.if.else:
; predecessors: %bb.0
  successors: %bb.2(0x80000000); %bb.2(100.00%)

  renamable $x10 = LW $x2, 4 :: (load (s32) from %fixed-stack.0)
  PseudoBR %bb.2

# End machine code for function __rem_pio2.

@topperc
Copy link
Collaborator Author

topperc commented Jan 28, 2025

Hi,

Sorry for the late answer, I created a reduced test: https://godbolt.org/z/sPs4E16x6

Regards, Gergely

This is the relevant part:

*** MachineFunction at end of ISel ***
# Machine code for function __rem_pio2: IsSSA, TracksLiveness
Frame Objects:
  fi#-2: size=4, align=4, fixed, at location [SP+4]
  fi#-1: size=4, align=16, fixed, at location [SP]
Function Live Ins: $x17 in %7

bb.0.entry:
  successors: %bb.3(0x40000000), %bb.2(0x40000000); %bb.3(50.00%), %bb.2(50.00%)
  liveins: $x17
  %7:gpr = COPY $x17
  %10:gpr = ANDI %7:gpr, 1
  %9:gprnox0 = LW %fixed-stack.0, 0 :: (load (s32) from %fixed-stack.0)
  %8:gprnox0 = LW %fixed-stack.1, 0 :: (load (s32) from %fixed-stack.1, align 16)
  BNE killed %10:gpr, $x0, %bb.3
  PseudoBR %bb.2

bb.1.common.ret:
; predecessors: %bb.2, %bb.3

  %13:gpr = COPY $x0
  $x10 = COPY %13:gpr
  PseudoRET implicit $x10

bb.2.if.then7:
; predecessors: %bb.0
  successors: %bb.1(0x80000000); %bb.1(100.00%)

  %11:gprpair = FCVT_D_W_IN32X $x0, 0
  PseudoRV32ZdinxSD killed %11:gprpair, %8:gprnox0, 0 :: (store (s64) into %ir.arrayidx13)
  PseudoBR %bb.1

bb.3.if.else:
; predecessors: %bb.0
  successors: %bb.1(0x80000000); %bb.1(100.00%)

  %12:gprpair = FCVT_D_W_IN32X $x0, 0
  PseudoRV32ZdinxSD killed %12:gprpair, %9:gprnox0, 0 :: (store (s64) into %ir.arrayidx20)
  PseudoBR %bb.1

# End machine code for function __rem_pio2.
# *** IR Dump After Tail Duplication (tailduplication) ***:
# Machine code for function __rem_pio2: NoPHIs, TracksLiveness, NoVRegs, TiedOpsRewritten, TracksDebugUserValues
Frame Objects:
  fi#-2: size=4, align=4, fixed, at location [SP+4]
  fi#-1: size=4, align=16, fixed, at location [SP]
Function Live Ins: $x17

bb.0.entry:
  successors: %bb.3(0x40000000), %bb.1(0x40000000); %bb.3(50.00%), %bb.1(50.00%)
  liveins: $x17
  renamable $x10 = ANDI killed renamable $x17, 1
  BNE killed renamable $x10, $x0, %bb.3

bb.1.if.then7:
; predecessors: %bb.0
  successors: %bb.2(0x80000000); %bb.2(100.00%)

  renamable $x10 = LW $x2, 0 :: (load (s32) from %fixed-stack.1, align 16)

bb.2.common.ret:
; predecessors: %bb.1, %bb.3
  liveins: $x10
  renamable $x12_x13 = FCVT_D_W_IN32X $x0, 0
  PseudoRV32ZdinxSD killed renamable $x12_x13, killed renamable $x10, 0 :: (store (s64) into %ir.arrayidx13), (store (s64) into %ir.arrayidx20)
  $x10 = COPY $x0
  PseudoRET implicit $x10

bb.3.if.else:
; predecessors: %bb.0
  successors: %bb.2(0x80000000); %bb.2(100.00%)

  renamable $x10 = LW $x2, 4 :: (load (s32) from %fixed-stack.0)
  PseudoBR %bb.2

# End machine code for function __rem_pio2.

Should be fixed after d4af658

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants