20
20
#include " llvm/CodeGen/GlobalISel/InstructionSelector.h"
21
21
#include " llvm/CodeGen/GlobalISel/MIPatternMatch.h"
22
22
#include " llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
23
+ #include " llvm/CodeGen/MachineJumpTableInfo.h"
23
24
#include " llvm/IR/IntrinsicsRISCV.h"
24
25
#include " llvm/Support/Debug.h"
25
26
@@ -64,6 +65,8 @@ class RISCVInstructionSelector : public InstructionSelector {
64
65
bool materializeImm (Register Reg, int64_t Imm, MachineIRBuilder &MIB) const ;
65
66
bool selectGlobalValue (MachineInstr &MI, MachineIRBuilder &MIB,
66
67
MachineRegisterInfo &MRI) const ;
68
+ bool selectJumpTable (MachineInstr &MI, MachineIRBuilder &MIB,
69
+ MachineRegisterInfo &MRI) const ;
67
70
bool selectSExtInreg (MachineInstr &MI, MachineIRBuilder &MIB) const ;
68
71
bool selectSelect (MachineInstr &MI, MachineIRBuilder &MIB,
69
72
MachineRegisterInfo &MRI) const ;
@@ -483,6 +486,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
483
486
}
484
487
case TargetOpcode::G_GLOBAL_VALUE:
485
488
return selectGlobalValue (MI, MIB, MRI);
489
+ case TargetOpcode::G_JUMP_TABLE:
490
+ return selectJumpTable (MI, MIB, MRI);
486
491
case TargetOpcode::G_BRCOND: {
487
492
Register LHS, RHS;
488
493
RISCVCC::CondCode CC;
@@ -493,6 +498,58 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
493
498
MI.eraseFromParent ();
494
499
return constrainSelectedInstRegOperands (*Bcc, TII, TRI, RBI);
495
500
}
501
+ case TargetOpcode::G_BRJT: {
502
+ // FIXME: Move to legalization?
503
+ const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo ();
504
+ unsigned EntrySize = MJTI->getEntrySize (MF.getDataLayout ());
505
+ assert ((EntrySize == 4 || (Subtarget->is64Bit () && EntrySize == 8 )) &&
506
+ " Unsupported jump-table entry size" );
507
+ assert (
508
+ (MJTI->getEntryKind () == MachineJumpTableInfo::EK_LabelDifference32 ||
509
+ MJTI->getEntryKind () == MachineJumpTableInfo::EK_Custom32 ||
510
+ MJTI->getEntryKind () == MachineJumpTableInfo::EK_BlockAddress) &&
511
+ " Unexpected jump-table entry kind" );
512
+
513
+ auto SLL =
514
+ MIB.buildInstr (RISCV::SLLI, {&RISCV::GPRRegClass}, {MI.getOperand (2 )})
515
+ .addImm (Log2_32 (EntrySize));
516
+ if (!SLL.constrainAllUses (TII, TRI, RBI))
517
+ return false ;
518
+
519
+ // TODO: Use SHXADD. Moving to legalization would fix this automatically.
520
+ auto ADD = MIB.buildInstr (RISCV::ADD, {&RISCV::GPRRegClass},
521
+ {MI.getOperand (0 ), SLL.getReg (0 )});
522
+ if (!ADD.constrainAllUses (TII, TRI, RBI))
523
+ return false ;
524
+
525
+ unsigned LdOpc = EntrySize == 8 ? RISCV::LD : RISCV::LW;
526
+ auto Dest =
527
+ MIB.buildInstr (LdOpc, {&RISCV::GPRRegClass}, {ADD.getReg (0 )})
528
+ .addImm (0 )
529
+ .addMemOperand (MF.getMachineMemOperand (
530
+ MachinePointerInfo::getJumpTable (MF), MachineMemOperand::MOLoad,
531
+ EntrySize, Align (MJTI->getEntryAlignment (MF.getDataLayout ()))));
532
+ if (!Dest.constrainAllUses (TII, TRI, RBI))
533
+ return false ;
534
+
535
+ // If the Kind is EK_LabelDifference32, the table stores an offset from
536
+ // the location of the table. Add the table address to get an absolute
537
+ // address.
538
+ if (MJTI->getEntryKind () == MachineJumpTableInfo::EK_LabelDifference32) {
539
+ Dest = MIB.buildInstr (RISCV::ADD, {&RISCV::GPRRegClass},
540
+ {Dest.getReg (0 ), MI.getOperand (0 )});
541
+ if (!Dest.constrainAllUses (TII, TRI, RBI))
542
+ return false ;
543
+ }
544
+
545
+ auto Branch =
546
+ MIB.buildInstr (RISCV::PseudoBRIND, {}, {Dest.getReg (0 )}).addImm (0 );
547
+ if (!Branch.constrainAllUses (TII, TRI, RBI))
548
+ return false ;
549
+
550
+ MI.eraseFromParent ();
551
+ return true ;
552
+ }
496
553
case TargetOpcode::G_SEXT_INREG:
497
554
return selectSExtInreg (MI, MIB);
498
555
case TargetOpcode::G_FRAME_INDEX: {
@@ -784,6 +841,97 @@ bool RISCVInstructionSelector::selectGlobalValue(
784
841
return false ;
785
842
}
786
843
844
+ // FIXME: This is very similar to selectGlobalValue. Merge somehow?
845
+ bool RISCVInstructionSelector::selectJumpTable (MachineInstr &MI,
846
+ MachineIRBuilder &MIB,
847
+ MachineRegisterInfo &MRI) const {
848
+ assert (MI.getOpcode () == TargetOpcode::G_JUMP_TABLE &&
849
+ " Expected G_JUMP_TABLE" );
850
+
851
+ int Idx = MI.getOperand (1 ).getIndex ();
852
+
853
+ Register DefReg = MI.getOperand (0 ).getReg ();
854
+ const LLT DefTy = MRI.getType (DefReg);
855
+ MachineInstr *Result = nullptr ;
856
+
857
+ // When HWASAN is used and tagging of global variables is enabled
858
+ // they should be accessed via the GOT, since the tagged address of a global
859
+ // is incompatible with existing code models. This also applies to non-pic
860
+ // mode.
861
+ if (TM.isPositionIndependent () || Subtarget->allowTaggedGlobals ()) {
862
+ if (!Subtarget->allowTaggedGlobals ()) {
863
+ // Use PC-relative addressing to access the symbol. This generates the
864
+ // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
865
+ // %pcrel_lo(auipc)).
866
+ Result =
867
+ MIB.buildInstr (RISCV::PseudoLLA, {DefReg}, {}).addJumpTableIndex (Idx);
868
+ } else {
869
+ // Use PC-relative addressing to access the GOT for this symbol, then
870
+ // load the address from the GOT. This generates the pattern (PseudoLGA
871
+ // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
872
+ // %pcrel_lo(auipc))).
873
+ MachineFunction &MF = *MI.getParent ()->getParent ();
874
+ MachineMemOperand *MemOp = MF.getMachineMemOperand (
875
+ MachinePointerInfo::getGOT (MF),
876
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
877
+ MachineMemOperand::MOInvariant,
878
+ DefTy, Align (DefTy.getSizeInBits () / 8 ));
879
+
880
+ Result = MIB.buildInstr (RISCV::PseudoLGA, {DefReg}, {})
881
+ .addJumpTableIndex (Idx)
882
+ .addMemOperand (MemOp);
883
+ }
884
+
885
+ if (!constrainSelectedInstRegOperands (*Result, TII, TRI, RBI))
886
+ return false ;
887
+
888
+ MI.eraseFromParent ();
889
+ return true ;
890
+ }
891
+
892
+ switch (TM.getCodeModel ()) {
893
+ default : {
894
+ reportGISelFailure (const_cast <MachineFunction &>(*MF), *TPC, *MORE,
895
+ getName (), " Unsupported code model for lowering" , MI);
896
+ return false ;
897
+ }
898
+ case CodeModel::Small: {
899
+ // Must lie within a single 2 GiB address range and must lie between
900
+ // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
901
+ // (lui %hi(sym)) %lo(sym)).
902
+ Register AddrHiDest = MRI.createVirtualRegister (&RISCV::GPRRegClass);
903
+ MachineInstr *AddrHi = MIB.buildInstr (RISCV::LUI, {AddrHiDest}, {})
904
+ .addJumpTableIndex (Idx, RISCVII::MO_HI);
905
+
906
+ if (!constrainSelectedInstRegOperands (*AddrHi, TII, TRI, RBI))
907
+ return false ;
908
+
909
+ Result = MIB.buildInstr (RISCV::ADDI, {DefReg}, {AddrHiDest})
910
+ .addJumpTableIndex (Idx, RISCVII::MO_LO);
911
+
912
+ if (!constrainSelectedInstRegOperands (*Result, TII, TRI, RBI))
913
+ return false ;
914
+
915
+ MI.eraseFromParent ();
916
+ return true ;
917
+ }
918
+ case CodeModel::Medium: {
919
+ // Generate a sequence for accessing addresses within any 2GiB range
920
+ // within the address space. This generates the pattern (PseudoLLA sym),
921
+ // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
922
+ Result =
923
+ MIB.buildInstr (RISCV::PseudoLLA, {DefReg}, {}).addJumpTableIndex (Idx);
924
+
925
+ if (!constrainSelectedInstRegOperands (*Result, TII, TRI, RBI))
926
+ return false ;
927
+
928
+ MI.eraseFromParent ();
929
+ return true ;
930
+ }
931
+ }
932
+ return false ;
933
+ }
934
+
787
935
bool RISCVInstructionSelector::selectSExtInreg (MachineInstr &MI,
788
936
MachineIRBuilder &MIB) const {
789
937
if (!STI.isRV64 ())
0 commit comments