summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Target/ARM/MachineInstrTest.cpp
blob: 77bba08dcbc8c1f1e718d193c4bba1f0b3cf0f21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include "ARMBaseInstrInfo.h"
#include "ARMSubtarget.h"
#include "ARMTargetMachine.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"

#include "gtest/gtest.h"

using namespace llvm;

// Test for instructions that aren't immediately obviously valid within a
// tail-predicated loop. This should be marked up in their tablegen
// descriptions. Currently the horizontal vector operations are tagged.
// TODO Add instructions that perform:
// - truncation,
// - extensions,
// - byte swapping,
// - others?
TEST(MachineInstrInvalidTailPredication, IsCorrect) {
  LLVMInitializeARMTargetInfo();
  LLVMInitializeARMTarget();
  LLVMInitializeARMTargetMC();

  auto TT(Triple::normalize("thumbv8.1m.main-arm-none-eabi"));
  std::string Error;
  const Target *T = TargetRegistry::lookupTarget(TT, Error);
  if (!T) {
    dbgs() << Error;
    return;
  }

  TargetOptions Options;
  auto TM = std::unique_ptr<LLVMTargetMachine>(
    static_cast<LLVMTargetMachine*>(
      T->createTargetMachine(TT, "generic", "", Options, None, None,
                             CodeGenOpt::Default)));
  auto MII = TM->getMCInstrInfo();

  using namespace ARM;

  auto IsInvalidTPOpcode = [](unsigned Opcode) {
    switch (Opcode) {
    case MVE_VABAVs8:
    case MVE_VABAVs16:
    case MVE_VABAVs32:
    case MVE_VABAVu8:
    case MVE_VABAVu16:
    case MVE_VABAVu32:
    case MVE_VADDVs8acc:
    case MVE_VADDVs16acc:
    case MVE_VADDVs32acc:
    case MVE_VADDVu8acc:
    case MVE_VADDVu16acc:
    case MVE_VADDVu32acc:
    case MVE_VADDVs8no_acc:
    case MVE_VADDVs16no_acc:
    case MVE_VADDVs32no_acc:
    case MVE_VADDVu8no_acc:
    case MVE_VADDVu16no_acc:
    case MVE_VADDVu32no_acc:
    case MVE_VADDLVs32no_acc:
    case MVE_VADDLVu32no_acc:
    case MVE_VADDLVs32acc:
    case MVE_VADDLVu32acc:
    case MVE_VMLADAVas16:
    case MVE_VMLADAVas32:
    case MVE_VMLADAVas8:
    case MVE_VMLADAVau16:
    case MVE_VMLADAVau32:
    case MVE_VMLADAVau8:
    case MVE_VMLADAVaxs16:
    case MVE_VMLADAVaxs32:
    case MVE_VMLADAVaxs8:
    case MVE_VMLADAVs16:
    case MVE_VMLADAVs32:
    case MVE_VMLADAVs8:
    case MVE_VMLADAVu16:
    case MVE_VMLADAVu32:
    case MVE_VMLADAVu8:
    case MVE_VMLADAVxs16:
    case MVE_VMLADAVxs32:
    case MVE_VMLADAVxs8:
    case MVE_VMLALDAVas16:
    case MVE_VMLALDAVas32:
    case MVE_VMLALDAVau16:
    case MVE_VMLALDAVau32:
    case MVE_VMLALDAVaxs16:
    case MVE_VMLALDAVaxs32:
    case MVE_VMLALDAVs16:
    case MVE_VMLALDAVs32:
    case MVE_VMLALDAVu16:
    case MVE_VMLALDAVu32:
    case MVE_VMLALDAVxs16:
    case MVE_VMLALDAVxs32:
    case MVE_VMLSDAVas16:
    case MVE_VMLSDAVas32:
    case MVE_VMLSDAVas8:
    case MVE_VMLSDAVaxs16:
    case MVE_VMLSDAVaxs32:
    case MVE_VMLSDAVaxs8:
    case MVE_VMLSDAVs16:
    case MVE_VMLSDAVs32:
    case MVE_VMLSDAVs8:
    case MVE_VMLSDAVxs16:
    case MVE_VMLSDAVxs32:
    case MVE_VMLSDAVxs8:
    case MVE_VMLSLDAVas16:
    case MVE_VMLSLDAVas32:
    case MVE_VMLSLDAVaxs16:
    case MVE_VMLSLDAVaxs32:
    case MVE_VMLSLDAVs16:
    case MVE_VMLSLDAVs32:
    case MVE_VMLSLDAVxs16:
    case MVE_VMLSLDAVxs32:
    case MVE_VRMLALDAVHas32:
    case MVE_VRMLALDAVHau32:
    case MVE_VRMLALDAVHaxs32:
    case MVE_VRMLALDAVHs32:
    case MVE_VRMLALDAVHu32:
    case MVE_VRMLALDAVHxs32:
    case MVE_VRMLSLDAVHas32:
    case MVE_VRMLSLDAVHaxs32:
    case MVE_VRMLSLDAVHs32:
    case MVE_VRMLSLDAVHxs32:
    case MVE_VMAXNMVf16:
    case MVE_VMINNMVf16:
    case MVE_VMAXNMVf32:
    case MVE_VMINNMVf32:
    case MVE_VMAXNMAVf16:
    case MVE_VMINNMAVf16:
    case MVE_VMAXNMAVf32:
    case MVE_VMINNMAVf32:
    case MVE_VMAXVs8:
    case MVE_VMAXVs16:
    case MVE_VMAXVs32:
    case MVE_VMAXVu8:
    case MVE_VMAXVu16:
    case MVE_VMAXVu32:
    case MVE_VMINVs8:
    case MVE_VMINVs16:
    case MVE_VMINVs32:
    case MVE_VMINVu8:
    case MVE_VMINVu16:
    case MVE_VMINVu32:
    case MVE_VMAXAVs8:
    case MVE_VMAXAVs16:
    case MVE_VMAXAVs32:
    case MVE_VMINAVs8:
    case MVE_VMINAVs16:
    case MVE_VMINAVs32:
      return true;
    default:
      return false;
    }
  };

  for (unsigned i = 0; i < ARM::INSTRUCTION_LIST_END; ++i) {
    uint64_t Flags = MII->get(i).TSFlags;
    bool Invalid = (Flags & ARMII::InvalidForTailPredication) != 0;
    ASSERT_EQ(IsInvalidTPOpcode(i), Invalid)
        << MII->getName(i)
        << ": mismatched expectation for tail-predicated safety\n";
  }
}
OpenPOWER on IntegriCloud