diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -416,6 +416,9 @@ def FeatureLS64 : SubtargetFeature<"ls64", "HasLS64", "true", "Enable Armv8.7-A LD64B/ST64B Accelerator Extension">; +def FeatureHBC : SubtargetFeature<"hbc", "HasHBC", + "true", "Enable Armv8.8-A Hinted Conditional Branches Extension">; + def FeatureBRBE : SubtargetFeature<"brbe", "HasBRBE", "true", "Enable Branch Record Buffer Extension">; @@ -499,7 +502,7 @@ def HasV8_8aOps : SubtargetFeature< "v8.8a", "HasV8_8aOps", "true", "Support ARM v8.8a instructions", - [HasV8_7aOps]>; + [HasV8_7aOps, FeatureHBC]>; def HasV9_0aOps : SubtargetFeature< "v9a", "HasV9_0aOps", "true", "Support ARM v9a instructions", diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1816,10 +1816,10 @@ let OperandType = "OPERAND_PCREL"; } -class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target), - "b", ".$cond\t$target", "", - [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, - Sched<[WriteBr]> { +class BranchCond + : I<(outs), (ins ccode:$cond, am_brcond:$target), + mnemonic, ".$cond\t$target", "", + [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> { let isBranch = 1; let isTerminator = 1; let Uses = [NZCV]; @@ -1828,7 +1828,7 @@ bits<19> target; let Inst{31-24} = 0b01010100; let Inst{23-5} = target; - let Inst{4} = 0; + let Inst{4} = bit4; let Inst{3-0} = cond; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -198,6 +198,8 @@ AssemblerPredicate<(all_of FeatureBRBE), "brbe">; def HasSPE_EEF : Predicate<"Subtarget->hasSPE_EEF()">, AssemblerPredicate<(all_of FeatureSPE_EEF), "spe-eef">; +def HasHBC : Predicate<"Subtarget->hasHBC()">, + AssemblerPredicate<(all_of FeatureHBC), "hbc">; def IsLE : Predicate<"Subtarget->isLittleEndian()">; def IsBE : Predicate<"!Subtarget->isLittleEndian()">; def IsWindows : Predicate<"Subtarget->isTargetWindows()">; @@ -2362,7 +2364,12 @@ //===----------------------------------------------------------------------===// // Conditional branch (immediate) instruction. //===----------------------------------------------------------------------===// -def Bcc : BranchCond; +def Bcc : BranchCond<0, "b">; + +// Armv8.8-A variant form which hints to the branch predictor that +// this branch is very likely to go the same way nearly all the time +// (even though it is not known at compile time _which_ way that is). +def BCcc : BranchCond<1, "bc">, Requires<[HasHBC]>; //===----------------------------------------------------------------------===// // Compare-and-branch instructions. diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -189,6 +189,9 @@ bool HasHCX = false; bool HasLS64 = false; + // Armv8.8-A Extensions + bool HasHBC = false; + // Arm SVE2 extensions bool HasSVE2 = false; bool HasSVE2AES = false; @@ -573,6 +576,7 @@ bool hasRCPC_IMMO() const { return HasRCPC_IMMO; } bool hasEL2VMSA() const { return HasEL2VMSA; } bool hasEL3() const { return HasEL3; } + bool hasHBC() const { return HasHBC; } bool fixCortexA53_835769() const { return FixCortexA53_835769; } diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -4533,7 +4533,7 @@ Mnemonic = Head; // Handle condition codes for a branch mnemonic - if (Head == "b" && Next != StringRef::npos) { + if ((Head == "b" || Head == "bc") && Next != StringRef::npos) { Start = Next; Next = Name.find('.', Start + 1); Head = Name.slice(Start + 1, Next); diff --git a/llvm/test/MC/AArch64/armv8.8a-hbc.s b/llvm/test/MC/AArch64/armv8.8a-hbc.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/armv8.8a-hbc.s @@ -0,0 +1,75 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+hbc < %s | FileCheck %s +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.8a < %s | FileCheck %s +// RUN: not llvm-mc -triple aarch64-none-linux-gnu < %s 2>&1 | FileCheck --check-prefix=CHECK-NO-HBC-ERR %s + +lbl: + bc.eq lbl + bc.ne lbl + bc.cs lbl + bc.hs lbl + bc.lo lbl + bc.cc lbl + bc.mi lbl + bc.pl lbl + bc.vs lbl + bc.vc lbl + bc.hi lbl + bc.ls lbl + bc.ge lbl + bc.lt lbl + bc.gt lbl + bc.le lbl + bc.al lbl + +// CHECK: bc.eq lbl // encoding: [0bAAA10000,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.ne lbl // encoding: [0bAAA10001,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.hs lbl // encoding: [0bAAA10010,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.hs lbl // encoding: [0bAAA10010,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.lo lbl // encoding: [0bAAA10011,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.lo lbl // encoding: [0bAAA10011,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.mi lbl // encoding: [0bAAA10100,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.pl lbl // encoding: [0bAAA10101,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.vs lbl // encoding: [0bAAA10110,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.vc lbl // encoding: [0bAAA10111,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.hi lbl // encoding: [0bAAA11000,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.ls lbl // encoding: [0bAAA11001,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.ge lbl // encoding: [0bAAA11010,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.lt lbl // encoding: [0bAAA11011,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.gt lbl // encoding: [0bAAA11100,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.le lbl // encoding: [0bAAA11101,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 +// CHECK: bc.al lbl // encoding: [0bAAA11110,A,A,0x54] +// CHECK: // fixup A - offset: 0, value: lbl, kind: fixup_aarch64_pcrel_branch19 + +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc +// CHECK-NO-HBC-ERR: [[@LINE-53]]:9: error: instruction requires: hbc diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.8a-hbc.txt b/llvm/test/MC/Disassembler/AArch64/armv8.8a-hbc.txt new file mode 100644 --- /dev/null +++ b/llvm/test/MC/Disassembler/AArch64/armv8.8a-hbc.txt @@ -0,0 +1,49 @@ +# RUN: llvm-mc -triple=aarch64 -mattr=+hbc -disassemble %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -mattr=+v8.8a -disassemble %s | FileCheck %s +# RUN: not llvm-mc -triple=aarch64 -disassemble %s 2>&1 | FileCheck --check-prefix=ERROR-NO-HBC %s + +[0x30,0x00,0x00,0x54] +# CHECK: bc.eq #4 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x51,0x00,0x00,0x54] +# CHECK: bc.ne #8 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x92,0x00,0x00,0x54] +# CHECK: bc.hs #16 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x13,0x01,0x00,0x54] +# CHECK: bc.lo #32 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x14,0x02,0x00,0x54] +# CHECK: bc.mi #64 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x15,0x04,0x00,0x54] +# CHECK: bc.pl #128 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x16,0x08,0x00,0x54] +# CHECK: bc.vs #256 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x17,0x10,0x00,0x54] +# CHECK: bc.vc #512 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x18,0x20,0x00,0x54] +# CHECK: bc.hi #1024 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x19,0x40,0x00,0x54] +# CHECK: bc.ls #2048 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x1a,0x80,0x00,0x54] +# CHECK: bc.ge #4096 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x1b,0x00,0x01,0x54] +# CHECK: bc.lt #8192 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x1c,0x00,0x02,0x54] +# CHECK: bc.gt #16384 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x1d,0x00,0x04,0x54] +# CHECK: bc.le #32768 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding +[0x1e,0x00,0x08,0x54] +# CHECK: bc.al #65536 +# ERROR-NO-HBC: [[@LINE-2]]:2: warning: invalid instruction encoding