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,50 @@ 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
+ unsigned EntrySize =
504
+ MF.getJumpTableInfo ()->getEntrySize (MF.getDataLayout ());
505
+ assert ((EntrySize == 4 || (Subtarget->is64Bit () && EntrySize == 8 )) &&
506
+ " Unsupported jump-table entry size" );
507
+
508
+ auto SLL =
509
+ MIB.buildInstr (RISCV::SLLI, {&RISCV::GPRRegClass}, {MI.getOperand (2 )})
510
+ .addImm (Log2_32 (EntrySize));
511
+ if (!SLL.constrainAllUses (TII, TRI, RBI))
512
+ return false ;
513
+
514
+ // TODO: Use SHXADD. Moving to legalization would fix this automatically.
515
+ auto ADD = MIB.buildInstr (RISCV::ADD, {&RISCV::GPRRegClass},
516
+ {MI.getOperand (0 ), SLL.getReg (0 )});
517
+ if (!ADD.constrainAllUses (TII, TRI, RBI))
518
+ return false ;
519
+
520
+ unsigned LdOpc = EntrySize == 8 ? RISCV::LD : RISCV::LW;
521
+ auto Dest =
522
+ MIB.buildInstr (LdOpc, {&RISCV::GPRRegClass}, {ADD.getReg (0 )})
523
+ .addImm (0 )
524
+ .addMemOperand (MF.getMachineMemOperand (
525
+ MachinePointerInfo::getJumpTable (MF), MachineMemOperand::MOLoad,
526
+ EntrySize, Align (EntrySize)));
527
+ if (!Dest.constrainAllUses (TII, TRI, RBI))
528
+ return false ;
529
+
530
+ if (MF.getTarget ().isPositionIndependent ()) {
531
+ Dest = MIB.buildInstr (RISCV::ADD, {&RISCV::GPRRegClass},
532
+ {Dest.getReg (0 ), MI.getOperand (0 )});
533
+ if (!Dest.constrainAllUses (TII, TRI, RBI))
534
+ return false ;
535
+ }
536
+
537
+ auto Branch =
538
+ MIB.buildInstr (RISCV::PseudoBRIND, {}, {Dest.getReg (0 )}).addImm (0 );
539
+ if (!Branch.constrainAllUses (TII, TRI, RBI))
540
+ return false ;
541
+
542
+ MI.eraseFromParent ();
543
+ return true ;
544
+ }
496
545
case TargetOpcode::G_SEXT_INREG:
497
546
return selectSExtInreg (MI, MIB);
498
547
case TargetOpcode::G_FRAME_INDEX: {
@@ -784,6 +833,97 @@ bool RISCVInstructionSelector::selectGlobalValue(
784
833
return false ;
785
834
}
786
835
836
+ // FIXME: This is very similar to selectGlobalValue. Merge somehow?
837
+ bool RISCVInstructionSelector::selectJumpTable (MachineInstr &MI,
838
+ MachineIRBuilder &MIB,
839
+ MachineRegisterInfo &MRI) const {
840
+ assert (MI.getOpcode () == TargetOpcode::G_JUMP_TABLE &&
841
+ " Expected G_JUMP_TABLE" );
842
+
843
+ int Idx = MI.getOperand (1 ).getIndex ();
844
+
845
+ Register DefReg = MI.getOperand (0 ).getReg ();
846
+ const LLT DefTy = MRI.getType (DefReg);
847
+ MachineInstr *Result = nullptr ;
848
+
849
+ // When HWASAN is used and tagging of global variables is enabled
850
+ // they should be accessed via the GOT, since the tagged address of a global
851
+ // is incompatible with existing code models. This also applies to non-pic
852
+ // mode.
853
+ if (TM.isPositionIndependent () || Subtarget->allowTaggedGlobals ()) {
854
+ if (!Subtarget->allowTaggedGlobals ()) {
855
+ // Use PC-relative addressing to access the symbol. This generates the
856
+ // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
857
+ // %pcrel_lo(auipc)).
858
+ Result =
859
+ MIB.buildInstr (RISCV::PseudoLLA, {DefReg}, {}).addJumpTableIndex (Idx);
860
+ } else {
861
+ // Use PC-relative addressing to access the GOT for this symbol, then
862
+ // load the address from the GOT. This generates the pattern (PseudoLGA
863
+ // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
864
+ // %pcrel_lo(auipc))).
865
+ MachineFunction &MF = *MI.getParent ()->getParent ();
866
+ MachineMemOperand *MemOp = MF.getMachineMemOperand (
867
+ MachinePointerInfo::getGOT (MF),
868
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
869
+ MachineMemOperand::MOInvariant,
870
+ DefTy, Align (DefTy.getSizeInBits () / 8 ));
871
+
872
+ Result = MIB.buildInstr (RISCV::PseudoLGA, {DefReg}, {})
873
+ .addJumpTableIndex (Idx)
874
+ .addMemOperand (MemOp);
875
+ }
876
+
877
+ if (!constrainSelectedInstRegOperands (*Result, TII, TRI, RBI))
878
+ return false ;
879
+
880
+ MI.eraseFromParent ();
881
+ return true ;
882
+ }
883
+
884
+ switch (TM.getCodeModel ()) {
885
+ default : {
886
+ reportGISelFailure (const_cast <MachineFunction &>(*MF), *TPC, *MORE,
887
+ getName (), " Unsupported code model for lowering" , MI);
888
+ return false ;
889
+ }
890
+ case CodeModel::Small: {
891
+ // Must lie within a single 2 GiB address range and must lie between
892
+ // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
893
+ // (lui %hi(sym)) %lo(sym)).
894
+ Register AddrHiDest = MRI.createVirtualRegister (&RISCV::GPRRegClass);
895
+ MachineInstr *AddrHi = MIB.buildInstr (RISCV::LUI, {AddrHiDest}, {})
896
+ .addJumpTableIndex (Idx, RISCVII::MO_HI);
897
+
898
+ if (!constrainSelectedInstRegOperands (*AddrHi, TII, TRI, RBI))
899
+ return false ;
900
+
901
+ Result = MIB.buildInstr (RISCV::ADDI, {DefReg}, {AddrHiDest})
902
+ .addJumpTableIndex (Idx, RISCVII::MO_LO);
903
+
904
+ if (!constrainSelectedInstRegOperands (*Result, TII, TRI, RBI))
905
+ return false ;
906
+
907
+ MI.eraseFromParent ();
908
+ return true ;
909
+ }
910
+ case CodeModel::Medium: {
911
+ // Generate a sequence for accessing addresses within any 2GiB range
912
+ // within the address space. This generates the pattern (PseudoLLA sym),
913
+ // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
914
+ Result =
915
+ MIB.buildInstr (RISCV::PseudoLLA, {DefReg}, {}).addJumpTableIndex (Idx);
916
+
917
+ if (!constrainSelectedInstRegOperands (*Result, TII, TRI, RBI))
918
+ return false ;
919
+
920
+ MI.eraseFromParent ();
921
+ return true ;
922
+ }
923
+ }
924
+ return false ;
925
+ }
926
+
787
927
bool RISCVInstructionSelector::selectSExtInreg (MachineInstr &MI,
788
928
MachineIRBuilder &MIB) const {
789
929
if (!STI.isRV64 ())
0 commit comments