@@ -213,6 +213,34 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
213213 Inst.getOpcode () == AArch64::ADDXrx64);
214214 }
215215
216+ bool isSUB (const MCInst &Inst) const override {
217+ const unsigned opcode = Inst.getOpcode ();
218+ switch (opcode) {
219+ case AArch64::SUBSWri:
220+ case AArch64::SUBSWrr:
221+ case AArch64::SUBSWrs:
222+ case AArch64::SUBSWrx:
223+ case AArch64::SUBSXri:
224+ case AArch64::SUBSXrr:
225+ case AArch64::SUBSXrs:
226+ case AArch64::SUBSXrx:
227+ case AArch64::SUBSXrx64:
228+ case AArch64::SUBWri:
229+ case AArch64::SUBWrr:
230+ case AArch64::SUBWrs:
231+ case AArch64::SUBWrx:
232+ case AArch64::SUBXri:
233+ case AArch64::SUBXrr:
234+ case AArch64::SUBXrs:
235+ case AArch64::SUBXrx:
236+ case AArch64::SUBXrx64:
237+ return true ;
238+ default :
239+ return false ;
240+ }
241+ llvm_unreachable (" " );
242+ }
243+
216244 bool isLDRB (const MCInst &Inst) const {
217245 return (Inst.getOpcode () == AArch64::LDRBBpost ||
218246 Inst.getOpcode () == AArch64::LDRBBpre ||
@@ -652,6 +680,34 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
652680 // / # of this BB)
653681 // / br x0 # Indirect jump instruction
654682 // /
683+ // / adrp + ldr pair instructions of JT
684+ // / adrp x3, :got:jump_table
685+ // / ldr x1, [x1, #value]
686+ // / ldrh w1, [x1, w3, uxtw #1]
687+ // / adr x3, 573ae4
688+ // / add x1, x3, w1, sxth #2
689+ // / br x1
690+ // /
691+ // / lld/test/ELF/aarch64-adrp-ldr-got.s
692+ // / if .rodata and .text are sufficiently (<1M)
693+ // / close to each other so that the adrp + ldr pair can be relaxed to
694+ // / nop + adr.
695+ // / nop #
696+ // / adr x0, #6d8f8 # Get JT table address
697+ // / ldrh w0, [x0, w4, uxtw #1] # Loads JT entry
698+ // / adr x2, 1479b0 # Get PC first instruction for next BB
699+ // / add x0, x2, w0, sxth #2 # Finish building branch target
700+ // / # (entries in JT are relative to the end
701+ // / # of this BB)
702+ // / br x0 # Indirect jump instruction
703+ // /
704+ // / sub + ldr pair instructions of JT, JT address on the stack and other BB
705+ // / sub x1, x29, #0x4, lsl #12
706+ // / ldr x1, [x1, #14352]
707+ // / ldrh w1, [x1, w3, uxtw #1]
708+ // / adr x3, 573ae4
709+ // / add x1, x3, w1, sxth #2
710+ // / br x1
655711 bool analyzeIndirectBranchFragment (
656712 const MCInst &Inst,
657713 DenseMap<const MCInst *, SmallVector<MCInst *, 4 >> &UDChain,
@@ -753,45 +809,77 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
753809
754810 // Match ADD that calculates the JumpTable Base Address (not the offset)
755811 SmallVector<MCInst *, 4 > &UsesLoad = UDChain[DefLoad];
756- const MCInst *DefJTBaseAdd = UsesLoad[1 ];
812+ const MCInst *DefJTPageBias = UsesLoad[1 ];
757813 MCPhysReg From, To;
758- if (DefJTBaseAdd == nullptr || isLoadFromStack (*DefJTBaseAdd) ||
759- isRegToRegMove (*DefJTBaseAdd, From, To)) {
814+ JumpTable = nullptr ;
815+ if (DefJTPageBias == nullptr || isLoadFromStack (*DefJTPageBias) ||
816+ isRegToRegMove (*DefJTPageBias, From, To)) {
760817 // Sometimes base address may have been defined in another basic block
761818 // (hoisted). Return with no jump table info.
762- JumpTable = nullptr ;
763819 return true ;
764820 }
765821
766- if (DefJTBaseAdd->getOpcode () == AArch64::ADR) {
822+ if (isAddXri (*DefJTPageBias)) {
823+ if (DefJTPageBias->getOperand (2 ).isImm ())
824+ Offset = DefJTPageBias->getOperand (2 ).getImm ();
825+ SmallVector<MCInst *, 4 > &UsesJTBaseAdd = UDChain[DefJTPageBias];
826+ const MCInst *DefJTBasePage = UsesJTBaseAdd[1 ];
827+ if (DefJTBasePage == nullptr || isLoadFromStack (*DefJTBasePage)) {
828+ return true ;
829+ }
830+ assert (DefJTBasePage->getOpcode () == AArch64::ADRP &&
831+ " Failed to match jump table base page pattern! (2)" );
832+ if (DefJTBasePage->getOperand (1 ).isExpr ())
833+ JumpTable = DefJTBasePage->getOperand (1 ).getExpr ();
834+ return true ;
835+ } else if (isADR (*DefJTPageBias)) {
767836 // TODO: Handle the pattern where there is no adrp/add pair.
768837 // It also occurs when the binary is static.
769- // adr x13, 0x215a18 <_nl_value_type_LC_COLLATE+0x50>
838+ // nop
839+ // *adr x13, 0x215a18 <_nl_value_type_LC_COLLATE+0x50>
770840 // ldrh w13, [x13, w12, uxtw #1]
771841 // adr x12, 0x247b30 <__gettextparse+0x5b0>
772842 // add x13, x12, w13, sxth #2
773843 // br x13
774- errs () << " BOLT-WARNING: Failed to match indirect branch: "
775- " nop/adr instead of adrp/add \n " ;
776- return false ;
777- }
778-
779- assert (DefJTBaseAdd->getOpcode () == AArch64::ADDXri &&
780- " Failed to match jump table base address pattern! (1)" );
844+ SmallVector<MCInst *, 4 > &UsesJTNop = UDChain[DefJTPageBias];
845+ assert ((UsesJTNop.size () == 1 && UsesJTNop[0 ] == nullptr ) &&
846+ " Failed to match jump table pattern! (2)" );
847+ if (DefJTPageBias->getOperand (1 ).isExpr ()) {
848+ JumpTable = DefJTPageBias->getOperand (1 ).getExpr ();
849+ return true ;
850+ }
851+ } else if (mayLoad (*DefJTPageBias)) {
852+ if (isLoadFromStack (*DefJTPageBias))
853+ return true ;
781854
782- if (DefJTBaseAdd->getOperand (2 ).isImm ())
783- Offset = DefJTBaseAdd->getOperand (2 ).getImm ();
784- SmallVector<MCInst *, 4 > &UsesJTBaseAdd = UDChain[DefJTBaseAdd];
785- const MCInst *DefJTBasePage = UsesJTBaseAdd[1 ];
786- if (DefJTBasePage == nullptr || isLoadFromStack (*DefJTBasePage)) {
787- JumpTable = nullptr ;
788- return true ;
855+ SmallVector<MCInst *, 4 > &UsesJTBase = UDChain[DefJTPageBias];
856+ const MCInst *DefJTBasePage = UsesJTBase[1 ];
857+ if (DefJTBasePage == nullptr )
858+ return true ;
859+ if (DefJTBasePage->getOpcode () == AArch64::ADRP) {
860+ // test jmp-table-pattern-matching.s (3)
861+ if (DefJTBasePage->getOperand (1 ).isExpr ())
862+ JumpTable = DefJTBasePage->getOperand (1 ).getExpr ();
863+ return true ;
864+ } else {
865+ // Base address may have been defined in another basic block
866+ // and sub instruction can be used to get base page address
867+ // jmp-table-pattern-matching.s (2)
868+ if (isSUB (*DefJTBasePage)) {
869+ for (const MCOperand &Operand : useOperands (*DefJTBasePage)) {
870+ if (!Operand.isReg ())
871+ continue ;
872+ const unsigned Reg = Operand.getReg ();
873+ if (Reg == AArch64::SP || Reg == AArch64::WSP ||
874+ Reg == AArch64::FP || Reg == AArch64::W29)
875+ return true ;
876+ }
877+ }
878+ }
789879 }
790- assert (DefJTBasePage->getOpcode () == AArch64::ADRP &&
791- " Failed to match jump table base page pattern! (2)" );
792- if (DefJTBasePage->getOperand (1 ).isExpr ())
793- JumpTable = DefJTBasePage->getOperand (1 ).getExpr ();
794- return true ;
880+
881+ assert (" Failed to match jump table pattern! (4)" );
882+ return false ;
795883 }
796884
797885 DenseMap<const MCInst *, SmallVector<MCInst *, 4 >>
0 commit comments