[llvm] r354768 - [ARM] Make fullfp16 instructions not conditionalisable.

Simon Tatham via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 25 02:39:54 PST 2019


Author: statham
Date: Mon Feb 25 02:39:53 2019
New Revision: 354768

URL: http://llvm.org/viewvc/llvm-project?rev=354768&view=rev
Log:
[ARM] Make fullfp16 instructions not conditionalisable.

More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.

In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.

(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)

So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.

I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.

Reviewers: SjoerdMeijer, t.p.northover, efriedma

Reviewed By: efriedma

Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D57823

Added:
    llvm/trunk/test/CodeGen/ARM/fp16-no-condition.ll
    llvm/trunk/test/MC/ARM/fullfp16-nopred.s   (with props)
    llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt   (with props)
    llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt   (with props)
Modified:
    llvm/trunk/include/llvm/Target/Target.td
    llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
    llvm/trunk/lib/Target/ARM/ARMInstrVFP.td
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
    llvm/trunk/utils/TableGen/CodeGenInstruction.cpp

Modified: llvm/trunk/include/llvm/Target/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=354768&r1=354767&r2=354768&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/Target.td (original)
+++ llvm/trunk/include/llvm/Target/Target.td Mon Feb 25 02:39:53 2019
@@ -456,7 +456,11 @@ class Instruction {
   bit isCommutable = 0;     // Is this 3 operand instruction commutable?
   bit isTerminator = 0;     // Is this part of the terminator for a basic block?
   bit isReMaterializable = 0; // Is this instruction re-materializable?
-  bit isPredicable = 0;     // Is this instruction predicable?
+  bit isPredicable = 0;     // 1 means this instruction is predicable
+                            // even if it does not have any operand
+                            // tablegen can identify as a predicate
+  bit isUnpredicable = 0;   // 1 means this instruction is not predicable
+                            // even if it _does_ have a predicate operand
   bit hasDelaySlot = 0;     // Does this instruction have an delay slot?
   bit usesCustomInserter = 0; // Pseudo instr needing special help.
   bit hasPostISelHook = 0;  // To be *adjusted* after isel by target hook.

Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=354768&r1=354767&r2=354768&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Mon Feb 25 02:39:53 2019
@@ -1555,6 +1555,8 @@ class AHI5<bits<4> opcod1, bits<2> opcod
 
   // Loads & stores operate on both NEON and VFP pipelines.
   let D = VFPNeonDomain;
+
+  let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
 }
 
 // VFP Load / store multiple pseudo instructions.
@@ -1902,6 +1904,8 @@ class AHuI<bits<5> opcod1, bits<2> opcod
   let Inst{11-8}  = 0b1001;   // Half precision
   let Inst{7-6}   = opcod4;
   let Inst{4}     = opcod5;
+
+  let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
 }
 
 // Half precision, unary, non-predicated
@@ -1930,6 +1934,8 @@ class AHuInp<bits<5> opcod1, bits<2> opc
   let Inst{11-8}  = 0b1001;   // Half precision
   let Inst{7-6}   = opcod4;
   let Inst{4}     = opcod5;
+
+  let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
 }
 
 // Half precision, binary
@@ -1956,6 +1962,8 @@ class AHbI<bits<5> opcod1, bits<2> opcod
   let Inst{11-8}  = 0b1001;   // Half precision
   let Inst{6}     = op6;
   let Inst{4}     = op4;
+
+  let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
 }
 
 // Half precision, binary, not predicated
@@ -1985,6 +1993,8 @@ class AHbInp<bits<5> opcod1, bits<2> opc
   let Inst{11-8}  = 0b1001;   // Half precision
   let Inst{6}     = opcod3;
   let Inst{4}     = 0;
+
+  let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
 }
 
 // VFP conversion instructions

Modified: llvm/trunk/lib/Target/ARM/ARMInstrVFP.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrVFP.td?rev=354768&r1=354767&r2=354768&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrVFP.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrVFP.td Mon Feb 25 02:39:53 2019
@@ -129,6 +129,7 @@ def VLDRS : ASI5<0b1101, 0b01, (outs SPR
   let D = VFPNeonDomain;
 }
 
+let isUnpredicable = 1 in
 def VLDRH : AHI5<0b1101, 0b01, (outs HPR:$Sd), (ins addrmode5fp16:$addr),
                  IIC_fpLoad16, "vldr", ".16\t$Sd, $addr",
                  [(set HPR:$Sd, (alignedload16 addrmode5fp16:$addr))]>,
@@ -148,6 +149,7 @@ def VSTRS : ASI5<0b1101, 0b00, (outs), (
   let D = VFPNeonDomain;
 }
 
+let isUnpredicable = 1 in
 def VSTRH : AHI5<0b1101, 0b00, (outs), (ins HPR:$Sd, addrmode5fp16:$addr),
                  IIC_fpStore16, "vstr", ".16\t$Sd, $addr",
                  [(alignedstore16 HPR:$Sd, addrmode5fp16:$addr)]>,
@@ -451,7 +453,7 @@ def VNMULH : AHbI<0b11100, 0b10, 1, 0,
 
 multiclass vsel_inst<string op, bits<2> opc, int CC> {
   let DecoderNamespace = "VFPV8", PostEncoderMethod = "",
-      Uses = [CPSR], AddedComplexity = 4 in {
+      Uses = [CPSR], AddedComplexity = 4, isUnpredicable = 1 in {
     def H : AHbInp<0b11100, opc, 0,
                    (outs HPR:$Sd), (ins HPR:$Sn, HPR:$Sm),
                    NoItinerary, !strconcat("vsel", op, ".f16\t$Sd, $Sn, $Sm"),
@@ -479,7 +481,8 @@ defm VSELEQ : vsel_inst<"eq", 0b00, 0>;
 defm VSELVS : vsel_inst<"vs", 0b01, 6>;
 
 multiclass vmaxmin_inst<string op, bit opc, SDNode SD> {
-  let DecoderNamespace = "VFPV8", PostEncoderMethod = "" in {
+  let DecoderNamespace = "VFPV8", PostEncoderMethod = "",
+      isUnpredicable = 1 in {
     def H : AHbInp<0b11101, 0b00, opc,
                    (outs HPR:$Sd), (ins HPR:$Sn, HPR:$Sm),
                    NoItinerary, !strconcat(op, ".f16\t$Sd, $Sn, $Sm"),
@@ -947,7 +950,8 @@ defm VRINTX : vrint_inst_zrx<"x", 1, 0,
 
 multiclass vrint_inst_anpm<string opc, bits<2> rm,
                            SDPatternOperator node = null_frag> {
-  let PostEncoderMethod = "", DecoderNamespace = "VFPV8" in {
+  let PostEncoderMethod = "", DecoderNamespace = "VFPV8",
+      isUnpredicable = 1 in {
     def H : AHuInp<0b11101, 0b11, 0b1000, 0b01, 0,
                    (outs SPR:$Sd), (ins SPR:$Sm),
                    NoItinerary, !strconcat("vrint", opc, ".f16\t$Sd, $Sm"),
@@ -1012,7 +1016,7 @@ def VMOVS  : ASuI<0b11101, 0b11, 0b0000,
                   IIC_fpUNA32, "vmov", ".f32\t$Sd, $Sm", []>;
 } // isMoveReg
 
-let PostEncoderMethod = "", DecoderNamespace = "VFPV8" in {
+let PostEncoderMethod = "", DecoderNamespace = "VFPV8", isUnpredicable = 1 in {
 def VMOVH  : ASuInp<0b11101, 0b11, 0b0000, 0b01, 0,
                   (outs SPR:$Sd), (ins SPR:$Sm),
                   IIC_fpUNA16, "vmovx.f16\t$Sd, $Sm", []>,
@@ -1221,6 +1225,8 @@ def VMOVRH : AVConv2I<0b11100001, 0b1001
 
   let Inst{6-5}   = 0b00;
   let Inst{3-0}   = 0b0000;
+
+  let isUnpredicable = 1;
 }
 
 // Move R->H, clearing top 16 bits
@@ -1241,6 +1247,8 @@ def VMOVHR : AVConv4I<0b11100000, 0b1001
 
   let Inst{6-5}   = 0b00;
   let Inst{3-0}   = 0b0000;
+
+  let isUnpredicable = 1;
 }
 
 // FMRDH: SPR -> GPR
@@ -1347,6 +1355,7 @@ def VSITOH : AVConv1IHs_Encode<0b11101,
                                []>,
              Sched<[WriteFPCVT]> {
   let Inst{7} = 1; // s32
+  let isUnpredicable = 1;
 }
 
 def : VFPNoNEONPat<(f16 (sint_to_fp GPR:$a)),
@@ -1392,6 +1401,7 @@ def VUITOH : AVConv1IHs_Encode<0b11101,
                                 []>,
              Sched<[WriteFPCVT]> {
   let Inst{7} = 0; // u32
+  let isUnpredicable = 1;
 }
 
 def : VFPNoNEONPat<(f16 (uint_to_fp GPR:$a)),
@@ -1496,6 +1506,7 @@ def VTOSIZH : AVConv1IsH_Encode<0b11101,
                                  []>,
               Sched<[WriteFPCVT]> {
   let Inst{7} = 1; // Z bit
+  let isUnpredicable = 1;
 }
 
 def : VFPNoNEONPat<(i32 (fp_to_sint HPR:$a)),
@@ -1542,6 +1553,7 @@ def VTOUIZH : AVConv1IsH_Encode<0b11101,
                                  []>,
               Sched<[WriteFPCVT]> {
   let Inst{7} = 1; // Z bit
+  let isUnpredicable = 1;
 }
 
 def : VFPNoNEONPat<(i32 (fp_to_uint HPR:$a)),
@@ -1571,6 +1583,7 @@ def VTOSIRH : AVConv1IsH_Encode<0b11101,
                                  []>,
               Sched<[WriteFPCVT]> {
   let Inst{7} = 0; // Z bit
+  let isUnpredicable = 1;
 }
 
 def VTOUIRD : AVConv1IsD_Encode<0b11101, 0b11, 0b1100, 0b1011,
@@ -1595,6 +1608,7 @@ def VTOUIRH : AVConv1IsH_Encode<0b11101,
                                  []>,
               Sched<[WriteFPCVT]> {
   let Inst{7} = 0; // Z bit
+  let isUnpredicable = 1;
 }
 }
 
@@ -1642,6 +1656,8 @@ class AVConv1XInsD_Encode<bits<5> op1, b
   let Predicates = [HasVFP2, HasDPVFP];
 }
 
+let isUnpredicable = 1 in {
+
 def VTOSHH : AVConv1XInsS_Encode<0b11101, 0b11, 0b1110, 0b1001, 0,
                        (outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
                  IIC_fpCVTHI, "vcvt", ".s16.f16\t$dst, $a, $fbits", []>,
@@ -1666,6 +1682,8 @@ def VTOULH : AVConv1XInsS_Encode<0b11101
              Requires<[HasFullFP16]>,
              Sched<[WriteFPCVT]>;
 
+} // End of 'let isUnpredicable = 1 in'
+
 def VTOSHS : AVConv1XInsS_Encode<0b11101, 0b11, 0b1110, 0b1010, 0,
                        (outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
                  IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits", []>,
@@ -1721,6 +1739,8 @@ def VTOULD : AVConv1XInsD_Encode<0b11101
 
 // Fixed-Point to FP:
 
+let isUnpredicable = 1 in {
+
 def VSHTOH : AVConv1XInsS_Encode<0b11101, 0b11, 0b1010, 0b1001, 0,
                        (outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
                  IIC_fpCVTIH, "vcvt", ".f16.s16\t$dst, $a, $fbits", []>,
@@ -1745,6 +1765,8 @@ def VULTOH : AVConv1XInsS_Encode<0b11101
              Requires<[HasFullFP16]>,
              Sched<[WriteFPCVT]>;
 
+} // End of 'let isUnpredicable = 1 in'
+
 def VSHTOS : AVConv1XInsS_Encode<0b11101, 0b11, 0b1010, 0b1010, 0,
                        (outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
                  IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits", []>,
@@ -2370,6 +2392,8 @@ def FCONSTH : VFPAI<(outs HPR:$Sd), (ins
   let Inst{11-8}  = 0b1001;     // Half precision
   let Inst{7-4}   = 0b0000;
   let Inst{3-0}   = imm{3-0};
+
+  let isUnpredicable = 1;
 }
 }
 

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=354768&r1=354767&r2=354768&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Mon Feb 25 02:39:53 2019
@@ -6478,6 +6478,18 @@ bool ARMAsmParser::validateInstruction(M
              Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
                  ARMCC::AL) {
     return Warning(Loc, "predicated instructions should be in IT block");
+  } else if (!MCID.isPredicable()) {
+    // Check the instruction doesn't have a predicate operand anyway
+    // that it's not allowed to use. Sometimes this happens in order
+    // to keep instructions the same shape even though one cannot
+    // legally be predicated, e.g. vmul.f16 vs vmul.f32.
+    for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) {
+      if (MCID.OpInfo[i].isPredicate()) {
+        if (Inst.getOperand(i).getImm() != ARMCC::AL)
+          return Error(Loc, "instruction is not predicable");
+        break;
+      }
+    }
   }
 
   // PC-setting instructions in an IT block, but not the last instruction of

Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp?rev=354768&r1=354767&r2=354768&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Mon Feb 25 02:39:53 2019
@@ -119,7 +119,7 @@ private:
   mutable ITStatus ITBlock;
 
   DecodeStatus AddThumbPredicate(MCInst&) const;
-  void UpdateThumbVFPPredicate(MCInst&) const;
+  void UpdateThumbVFPPredicate(DecodeStatus &, MCInst&) const;
 };
 
 } // end anonymous namespace
@@ -630,6 +630,8 @@ ThumbDisassembler::AddThumbPredicate(MCI
   for (unsigned i = 0; i < NumOps; ++i, ++I) {
     if (I == MI.end()) break;
     if (OpInfo[i].isPredicate()) {
+      if (CC != ARMCC::AL && !ARMInsts[MI.getOpcode()].isPredicable())
+        Check(S, SoftFail);
       I = MI.insert(I, MCOperand::createImm(CC));
       ++I;
       if (CC == ARMCC::AL)
@@ -655,7 +657,8 @@ ThumbDisassembler::AddThumbPredicate(MCI
 // mode, the auto-generated decoder will give them an (incorrect)
 // predicate operand.  We need to rewrite these operands based on the IT
 // context as a post-pass.
-void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const {
+void ThumbDisassembler::UpdateThumbVFPPredicate(
+  DecodeStatus &S, MCInst &MI) const {
   unsigned CC;
   CC = ITBlock.getITCC();
   if (CC == 0xF)
@@ -668,6 +671,8 @@ void ThumbDisassembler::UpdateThumbVFPPr
   unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
   for (unsigned i = 0; i < NumOps; ++i, ++I) {
     if (OpInfo[i].isPredicate() ) {
+      if (CC != ARMCC::AL && !ARMInsts[MI.getOpcode()].isPredicable())
+        Check(S, SoftFail);
       I->setImm(CC);
       ++I;
       if (CC == ARMCC::AL)
@@ -773,7 +778,7 @@ DecodeStatus ThumbDisassembler::getInstr
         decodeInstruction(DecoderTableVFP32, MI, Insn32, Address, this, STI);
     if (Result != MCDisassembler::Fail) {
       Size = 4;
-      UpdateThumbVFPPredicate(MI);
+      UpdateThumbVFPPredicate(Result, MI);
       return Result;
     }
   }
@@ -1110,16 +1115,19 @@ static DecodeStatus DecodeDPairSpacedReg
 
 static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
                                uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
   if (Val == 0xF) return MCDisassembler::Fail;
   // AL predicate is not allowed on Thumb1 branches.
   if (Inst.getOpcode() == ARM::tBcc && Val == 0xE)
     return MCDisassembler::Fail;
+  if (Val != ARMCC::AL && !ARMInsts[Inst.getOpcode()].isPredicable())
+    Check(S, MCDisassembler::SoftFail);
   Inst.addOperand(MCOperand::createImm(Val));
   if (Val == ARMCC::AL) {
     Inst.addOperand(MCOperand::createReg(0));
   } else
     Inst.addOperand(MCOperand::createReg(ARM::CPSR));
-  return MCDisassembler::Success;
+  return S;
 }
 
 static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val,

Added: llvm/trunk/test/CodeGen/ARM/fp16-no-condition.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fp16-no-condition.ll?rev=354768&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/fp16-no-condition.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/fp16-no-condition.ll Mon Feb 25 02:39:53 2019
@@ -0,0 +1,100 @@
+; RUN: llc -O3 -mtriple=armv8a-none-eabi -mattr=+fullfp16 -o - %s | FileCheck %s
+; RUN: llc -O3 -mtriple=thumbv8a-none-eabi -mattr=+fullfp16 -arm-no-restrict-it -o - %s | FileCheck %s
+
+; Require the vmul.f16 not to be predicated, because it's illegal to
+; do so with fp16 instructions
+define half @conditional_fmul_f16(half* %p) {
+; CHECK-LABEL: conditional_fmul_f16:
+; CHECK: vmul.f16
+entry:
+  %p1 = getelementptr half, half* %p, i32 1
+  %a = load half, half* %p, align 2
+  %threshold = load half, half* %p1, align 2
+  %flag = fcmp ogt half %a, %threshold
+  br i1 %flag, label %mul, label %out
+
+mul:
+  %p2 = getelementptr half, half* %p, i32 2
+  %mult = load half, half* %p2, align 2
+  %b = fmul half %a, %mult
+  br label %out
+
+out:
+  %sel = phi half [ %a, %entry ], [ %b, %mul ]
+  ret half %sel
+}
+
+; Expect that the corresponding vmul.f32 _will_ be predicated (to make
+; sure the previous test is really testing something)
+define float @conditional_fmul_f32(float* %p) {
+; CHECK-LABEL: conditional_fmul_f32:
+; CHECK: vmulgt.f32
+entry:
+  %p1 = getelementptr float, float* %p, i32 1
+  %a = load float, float* %p, align 2
+  %threshold = load float, float* %p1, align 2
+  %flag = fcmp ogt float %a, %threshold
+  br i1 %flag, label %mul, label %out
+
+mul:
+  %p2 = getelementptr float, float* %p, i32 2
+  %mult = load float, float* %p2, align 2
+  %b = fmul float %a, %mult
+  br label %out
+
+out:
+  %sel = phi float [ %a, %entry ], [ %b, %mul ]
+  ret float %sel
+}
+
+; Require the two comparisons to be done with unpredicated vcmp.f16
+; instructions (again, it is illegal to predicate them)
+define void @chained_comparisons_f16(half* %p) {
+; CHECK-LABEL: chained_comparisons_f16:
+; CHECK: vcmp.f16
+; CHECK: vcmp.f16
+entry:
+  %p1 = getelementptr half, half* %p, i32 1
+
+  %a = load half, half* %p, align 2
+  %b = load half, half* %p1, align 2
+
+  %aflag = fcmp oeq half %a, 0xH0000
+  %bflag = fcmp oeq half %b, 0xH0000
+  %flag = or i1 %aflag, %bflag
+  br i1 %flag, label %call, label %out
+
+call:
+  call void @external_function()
+  br label %out
+
+out:
+  ret void
+}
+
+; Again, do the corresponding test with 32-bit floats and check that
+; the second comparison _is_ predicated on the result of the first.
+define void @chained_comparisons_f32(float* %p) {
+; CHECK-LABEL: chained_comparisons_f32:
+; CHECK: vcmp.f32
+; CHECK: vcmpne.f32
+entry:
+  %p1 = getelementptr float, float* %p, i32 1
+
+  %a = load float, float* %p, align 2
+  %b = load float, float* %p1, align 2
+
+  %aflag = fcmp oeq float %a, 0x00000000
+  %bflag = fcmp oeq float %b, 0x00000000
+  %flag = or i1 %aflag, %bflag
+  br i1 %flag, label %call, label %out
+
+call:
+  call void @external_function()
+  br label %out
+
+out:
+  ret void
+}
+
+declare void @external_function()

Added: llvm/trunk/test/MC/ARM/fullfp16-nopred.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/fullfp16-nopred.s?rev=354768&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/fullfp16-nopred.s (added)
+++ llvm/trunk/test/MC/ARM/fullfp16-nopred.s Mon Feb 25 02:39:53 2019
@@ -0,0 +1,113 @@
+@ RUN: not llvm-mc -triple armv8a-none-eabi -mattr=+fullfp16 < %s 2>&1 | FileCheck %s
+@ RUN: not llvm-mc -triple armv8a-none-eabi -mattr=+fullfp16,+thumb-mode -arm-implicit-it always < %s 2>&1 | FileCheck %s
+
+  vaddeq.f16  s0, s1, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vsubne.f16  s0, s1, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vdivmi.f16  s0, s1, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vmulpl.f16  s0, s1, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vnmulvs.f16       s0, s1, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vmlavc.f16        s1, s2, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vmlshs.f16        s1, s2, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vnmlalo.f16       s1, s2, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vnmlscs.f16       s1, s2, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcmpcc.f16 s0, s1
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcmphi.f16 s2, #0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcmpels.f16       s1, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcmpege.f16       s0, #0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vabslt.f16        s0, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vneggt.f16        s0, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vsqrtle.f16       s0, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcvteq.f16.s32    s0, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcvtne.u32.f16    s0, s0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vcvtrmi.s32.f16  s0, s1
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vrintzhs.f16 s3, s24
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vrintrlo.f16 s0, s9
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vrintxcs.f16 s10, s14
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vfmalt.f16 s2, s7, s4
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vfmsgt.f16 s2, s7, s4
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vfnmale.f16 s2, s7, s4
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vfnmseq.f16 s2, s7, s4
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vldrpl.16 s1, [pc, #6]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vldrvs.16 s2, [pc, #510]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vldrvc.16 s3, [pc, #-510]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vldrhs.16 s4, [r4, #-18]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vstrlo.16 s1, [pc, #6]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vstrcs.16 s2, [pc, #510]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vstrcc.16 s3, [pc, #-510]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vstrhi.16 s4, [r4, #-18]
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vmovls.f16 s0, #1.0
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vmovge.f16 s1, r2
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable
+
+  vmovlt.f16 r3, s4
+@ CHECK: [[@LINE-1]]:3: error: instruction is not predicable

Propchange: llvm/trunk/test/MC/ARM/fullfp16-nopred.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: llvm/trunk/test/MC/ARM/fullfp16-nopred.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt?rev=354768&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt (added)
+++ llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt Mon Feb 25 02:39:53 2019
@@ -0,0 +1,6 @@
+# RUN: llvm-mc -disassemble -triple armv8a-none-eabi -mattr=+fullfp16 -show-encoding < %s 2>&1 | FileCheck %s
+
+# CHECK: [[@LINE+1]]:2: warning: potentially undefined instruction encoding
+[0x80,0x09,0x30,0xae]
+# CHECK-NOT: [[@LINE+1]]:2: warning
+[0x80,0x0a,0x30,0xae]

Propchange: llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: llvm/trunk/test/MC/Disassembler/ARM/fullfp16-arm-nopred.txt
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt?rev=354768&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt (added)
+++ llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt Mon Feb 25 02:39:53 2019
@@ -0,0 +1,9 @@
+# RUN: llvm-mc -disassemble -triple thumbv8a-none-eabi -mattr=+fullfp16,+thumb-mode -show-encoding < %s 2>&1 | FileCheck %s
+
+# CHECK: [[@LINE+2]]:2: warning: potentially undefined instruction encoding
+[0xc8,0xbf]
+[0x30,0xee,0x81,0x09]
+
+# CHECK-NOT: [[@LINE+2]]:2: warning
+[0xc8,0xbf]
+[0x30,0xee,0x81,0x0a]

Propchange: llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: llvm/trunk/test/MC/Disassembler/ARM/fullfp16-thumb-nopred.txt
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=354768&r1=354767&r2=354768&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Mon Feb 25 02:39:53 2019
@@ -377,7 +377,8 @@ CodeGenInstruction::CodeGenInstruction(R
   isAdd        = R->getValueAsBit("isAdd");
   isTrap       = R->getValueAsBit("isTrap");
   canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
-  isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
+  isPredicable = !R->getValueAsBit("isUnpredicable") && (
+      Operands.isPredicable || R->getValueAsBit("isPredicable"));
   isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
   isCommutable = R->getValueAsBit("isCommutable");
   isTerminator = R->getValueAsBit("isTerminator");




More information about the llvm-commits mailing list