347 lines · cpp
1#include "AArch64SMEAttributes.h"2#include "llvm/AsmParser/Parser.h"3#include "llvm/IR/Function.h"4#include "llvm/IR/InstrTypes.h"5#include "llvm/IR/Module.h"6#include "llvm/Support/SourceMgr.h"7 8#include "gtest/gtest.h"9 10using namespace llvm;11using SA = SMEAttrs;12using CA = SMECallAttrs;13 14std::unique_ptr<Module> parseIR(const char *IR) {15 static LLVMContext C;16 SMDiagnostic Err;17 return parseAssemblyString(IR, Err, C);18}19 20TEST(SMEAttributes, Constructors) {21 LLVMContext Context;22 23 ASSERT_TRUE(SA(*parseIR("declare void @foo()")->getFunction("foo"))24 .hasNonStreamingInterfaceAndBody());25 26 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_pstate_sm_body\"")27 ->getFunction("foo"))28 .hasNonStreamingInterface());29 30 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_pstate_sm_enabled\"")31 ->getFunction("foo"))32 .hasStreamingInterface());33 34 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_pstate_sm_body\"")35 ->getFunction("foo"))36 .hasStreamingBody());37 38 ASSERT_TRUE(39 SA(*parseIR("declare void @foo() \"aarch64_pstate_sm_compatible\"")40 ->getFunction("foo"))41 .hasStreamingCompatibleInterface());42 43 ASSERT_TRUE(44 SA(*parseIR("declare void @foo() \"aarch64_in_za\"")->getFunction("foo"))45 .isInZA());46 ASSERT_TRUE(47 SA(*parseIR("declare void @foo() \"aarch64_out_za\"")->getFunction("foo"))48 .isOutZA());49 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_inout_za\"")50 ->getFunction("foo"))51 .isInOutZA());52 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_preserves_za\"")53 ->getFunction("foo"))54 .isPreservesZA());55 ASSERT_TRUE(56 SA(*parseIR("declare void @foo() \"aarch64_new_za\"")->getFunction("foo"))57 .isNewZA());58 59 ASSERT_TRUE(60 SA(*parseIR("declare void @foo() \"aarch64_in_zt0\"")->getFunction("foo"))61 .isInZT0());62 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_out_zt0\"")63 ->getFunction("foo"))64 .isOutZT0());65 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_inout_zt0\"")66 ->getFunction("foo"))67 .isInOutZT0());68 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_preserves_zt0\"")69 ->getFunction("foo"))70 .isPreservesZT0());71 ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_new_zt0\"")72 ->getFunction("foo"))73 .isNewZT0());74 75 auto CallModule = parseIR("declare void @callee()\n"76 "define void @foo() {"77 "call void @callee() \"aarch64_zt0_undef\"\n"78 "ret void\n}");79 CallBase &Call =80 cast<CallBase>((CallModule->getFunction("foo")->begin()->front()));81 ASSERT_TRUE(SMECallAttrs(Call, nullptr).callsite().hasUndefZT0());82 83 // Invalid combinations.84 EXPECT_DEBUG_DEATH(SA(SA::SM_Enabled | SA::SM_Compatible),85 "SM_Enabled and SM_Compatible are mutually exclusive");86 87 // Test that the set() methods equally check validity.88 EXPECT_DEBUG_DEATH(SA(SA::SM_Enabled).set(SA::SM_Compatible),89 "SM_Enabled and SM_Compatible are mutually exclusive");90 EXPECT_DEBUG_DEATH(SA(SA::SM_Compatible).set(SA::SM_Enabled),91 "SM_Enabled and SM_Compatible are mutually exclusive");92}93 94TEST(SMEAttributes, Basics) {95 // Test PSTATE.SM interfaces.96 ASSERT_TRUE(SA(SA::Normal).hasNonStreamingInterfaceAndBody());97 ASSERT_TRUE(SA(SA::SM_Enabled).hasStreamingInterface());98 ASSERT_TRUE(SA(SA::SM_Body).hasStreamingBody());99 ASSERT_TRUE(SA(SA::SM_Body).hasNonStreamingInterface());100 ASSERT_FALSE(SA(SA::SM_Body).hasNonStreamingInterfaceAndBody());101 ASSERT_FALSE(SA(SA::SM_Body).hasStreamingInterface());102 ASSERT_TRUE(SA(SA::SM_Compatible).hasStreamingCompatibleInterface());103 ASSERT_TRUE(104 SA(SA::SM_Compatible | SA::SM_Body).hasStreamingCompatibleInterface());105 ASSERT_TRUE(SA(SA::SM_Compatible | SA::SM_Body).hasStreamingBody());106 ASSERT_FALSE(SA(SA::SM_Compatible | SA::SM_Body).hasNonStreamingInterface());107 108 // Test ZA State interfaces109 SA ZA_In = SA(SA::encodeZAState(SA::StateValue::In));110 ASSERT_TRUE(ZA_In.isInZA());111 ASSERT_FALSE(ZA_In.isOutZA());112 ASSERT_FALSE(ZA_In.isInOutZA());113 ASSERT_FALSE(ZA_In.isPreservesZA());114 ASSERT_FALSE(ZA_In.isNewZA());115 ASSERT_TRUE(ZA_In.sharesZA());116 ASSERT_TRUE(ZA_In.hasZAState());117 ASSERT_TRUE(ZA_In.hasSharedZAInterface());118 ASSERT_FALSE(ZA_In.hasPrivateZAInterface());119 120 SA ZA_Out = SA(SA::encodeZAState(SA::StateValue::Out));121 ASSERT_TRUE(ZA_Out.isOutZA());122 ASSERT_FALSE(ZA_Out.isInZA());123 ASSERT_FALSE(ZA_Out.isInOutZA());124 ASSERT_FALSE(ZA_Out.isPreservesZA());125 ASSERT_FALSE(ZA_Out.isNewZA());126 ASSERT_TRUE(ZA_Out.sharesZA());127 ASSERT_TRUE(ZA_Out.hasZAState());128 ASSERT_TRUE(ZA_Out.hasSharedZAInterface());129 ASSERT_FALSE(ZA_Out.hasPrivateZAInterface());130 131 SA ZA_InOut = SA(SA::encodeZAState(SA::StateValue::InOut));132 ASSERT_TRUE(ZA_InOut.isInOutZA());133 ASSERT_FALSE(ZA_InOut.isInZA());134 ASSERT_FALSE(ZA_InOut.isOutZA());135 ASSERT_FALSE(ZA_InOut.isPreservesZA());136 ASSERT_FALSE(ZA_InOut.isNewZA());137 ASSERT_TRUE(ZA_InOut.sharesZA());138 ASSERT_TRUE(ZA_InOut.hasZAState());139 ASSERT_TRUE(ZA_InOut.hasSharedZAInterface());140 ASSERT_FALSE(ZA_InOut.hasPrivateZAInterface());141 142 SA ZA_Preserved = SA(SA::encodeZAState(SA::StateValue::Preserved));143 ASSERT_TRUE(ZA_Preserved.isPreservesZA());144 ASSERT_FALSE(ZA_Preserved.isInZA());145 ASSERT_FALSE(ZA_Preserved.isOutZA());146 ASSERT_FALSE(ZA_Preserved.isInOutZA());147 ASSERT_FALSE(ZA_Preserved.isNewZA());148 ASSERT_TRUE(ZA_Preserved.sharesZA());149 ASSERT_TRUE(ZA_Preserved.hasZAState());150 ASSERT_TRUE(ZA_Preserved.hasSharedZAInterface());151 ASSERT_FALSE(ZA_Preserved.hasPrivateZAInterface());152 153 SA ZA_New = SA(SA::encodeZAState(SA::StateValue::New));154 ASSERT_TRUE(ZA_New.isNewZA());155 ASSERT_FALSE(ZA_New.isInZA());156 ASSERT_FALSE(ZA_New.isOutZA());157 ASSERT_FALSE(ZA_New.isInOutZA());158 ASSERT_FALSE(ZA_New.isPreservesZA());159 ASSERT_FALSE(ZA_New.sharesZA());160 ASSERT_TRUE(ZA_New.hasZAState());161 ASSERT_FALSE(ZA_New.hasSharedZAInterface());162 ASSERT_TRUE(ZA_New.hasPrivateZAInterface());163 164 ASSERT_FALSE(SA(SA::Normal).isInZA());165 ASSERT_FALSE(SA(SA::Normal).isOutZA());166 ASSERT_FALSE(SA(SA::Normal).isInOutZA());167 ASSERT_FALSE(SA(SA::Normal).isPreservesZA());168 ASSERT_FALSE(SA(SA::Normal).isNewZA());169 ASSERT_FALSE(SA(SA::Normal).sharesZA());170 ASSERT_FALSE(SA(SA::Normal).hasZAState());171 172 // Test ZT0 State interfaces173 SA ZT0_In = SA(SA::encodeZT0State(SA::StateValue::In));174 ASSERT_TRUE(ZT0_In.isInZT0());175 ASSERT_FALSE(ZT0_In.isOutZT0());176 ASSERT_FALSE(ZT0_In.isInOutZT0());177 ASSERT_FALSE(ZT0_In.isPreservesZT0());178 ASSERT_FALSE(ZT0_In.isNewZT0());179 ASSERT_TRUE(ZT0_In.sharesZT0());180 ASSERT_TRUE(ZT0_In.hasZT0State());181 ASSERT_TRUE(ZT0_In.hasSharedZAInterface());182 ASSERT_FALSE(ZT0_In.hasPrivateZAInterface());183 184 SA ZT0_Out = SA(SA::encodeZT0State(SA::StateValue::Out));185 ASSERT_TRUE(ZT0_Out.isOutZT0());186 ASSERT_FALSE(ZT0_Out.isInZT0());187 ASSERT_FALSE(ZT0_Out.isInOutZT0());188 ASSERT_FALSE(ZT0_Out.isPreservesZT0());189 ASSERT_FALSE(ZT0_Out.isNewZT0());190 ASSERT_TRUE(ZT0_Out.sharesZT0());191 ASSERT_TRUE(ZT0_Out.hasZT0State());192 ASSERT_TRUE(ZT0_Out.hasSharedZAInterface());193 ASSERT_FALSE(ZT0_Out.hasPrivateZAInterface());194 195 SA ZT0_InOut = SA(SA::encodeZT0State(SA::StateValue::InOut));196 ASSERT_TRUE(ZT0_InOut.isInOutZT0());197 ASSERT_FALSE(ZT0_InOut.isInZT0());198 ASSERT_FALSE(ZT0_InOut.isOutZT0());199 ASSERT_FALSE(ZT0_InOut.isPreservesZT0());200 ASSERT_FALSE(ZT0_InOut.isNewZT0());201 ASSERT_TRUE(ZT0_InOut.sharesZT0());202 ASSERT_TRUE(ZT0_InOut.hasZT0State());203 ASSERT_TRUE(ZT0_InOut.hasSharedZAInterface());204 ASSERT_FALSE(ZT0_InOut.hasPrivateZAInterface());205 206 SA ZT0_Preserved = SA(SA::encodeZT0State(SA::StateValue::Preserved));207 ASSERT_TRUE(ZT0_Preserved.isPreservesZT0());208 ASSERT_FALSE(ZT0_Preserved.isInZT0());209 ASSERT_FALSE(ZT0_Preserved.isOutZT0());210 ASSERT_FALSE(ZT0_Preserved.isInOutZT0());211 ASSERT_FALSE(ZT0_Preserved.isNewZT0());212 ASSERT_TRUE(ZT0_Preserved.sharesZT0());213 ASSERT_TRUE(ZT0_Preserved.hasZT0State());214 ASSERT_TRUE(ZT0_Preserved.hasSharedZAInterface());215 ASSERT_FALSE(ZT0_Preserved.hasPrivateZAInterface());216 217 SA ZT0_New = SA(SA::encodeZT0State(SA::StateValue::New));218 ASSERT_TRUE(ZT0_New.isNewZT0());219 ASSERT_FALSE(ZT0_New.isInZT0());220 ASSERT_FALSE(ZT0_New.isOutZT0());221 ASSERT_FALSE(ZT0_New.isInOutZT0());222 ASSERT_FALSE(ZT0_New.isPreservesZT0());223 ASSERT_FALSE(ZT0_New.sharesZT0());224 ASSERT_TRUE(ZT0_New.hasZT0State());225 ASSERT_FALSE(ZT0_New.hasSharedZAInterface());226 ASSERT_TRUE(ZT0_New.hasPrivateZAInterface());227 228 SA ZT0_Undef = SA(SA::ZT0_Undef | SA::encodeZT0State(SA::StateValue::New));229 ASSERT_TRUE(ZT0_Undef.isNewZT0());230 ASSERT_FALSE(ZT0_Undef.isInZT0());231 ASSERT_FALSE(ZT0_Undef.isOutZT0());232 ASSERT_FALSE(ZT0_Undef.isInOutZT0());233 ASSERT_FALSE(ZT0_Undef.isPreservesZT0());234 ASSERT_FALSE(ZT0_Undef.sharesZT0());235 ASSERT_TRUE(ZT0_Undef.hasZT0State());236 ASSERT_FALSE(ZT0_Undef.hasSharedZAInterface());237 ASSERT_TRUE(ZT0_Undef.hasPrivateZAInterface());238 ASSERT_TRUE(ZT0_Undef.hasUndefZT0());239 240 ASSERT_FALSE(SA(SA::Normal).isInZT0());241 ASSERT_FALSE(SA(SA::Normal).isOutZT0());242 ASSERT_FALSE(SA(SA::Normal).isInOutZT0());243 ASSERT_FALSE(SA(SA::Normal).isPreservesZT0());244 ASSERT_FALSE(SA(SA::Normal).isNewZT0());245 ASSERT_FALSE(SA(SA::Normal).sharesZT0());246 ASSERT_FALSE(SA(SA::Normal).hasZT0State());247}248 249TEST(SMEAttributes, Transitions) {250 // Normal -> Normal251 ASSERT_FALSE(CA(SA::Normal, SA::Normal).requiresSMChange());252 ASSERT_FALSE(CA(SA::Normal, SA::Normal).requiresPreservingZT0());253 ASSERT_FALSE(CA(SA::Normal, SA::Normal).requiresDisablingZABeforeCall());254 ASSERT_FALSE(CA(SA::Normal, SA::Normal).requiresEnablingZAAfterCall());255 // Normal -> Normal + LocallyStreaming256 ASSERT_FALSE(CA(SA::Normal, SA::Normal | SA::SM_Body).requiresSMChange());257 258 // Normal -> Streaming259 ASSERT_TRUE(CA(SA::Normal, SA::SM_Enabled).requiresSMChange());260 // Normal -> Streaming + LocallyStreaming261 ASSERT_TRUE(CA(SA::Normal, SA::SM_Enabled | SA::SM_Body).requiresSMChange());262 263 // Normal -> Streaming-compatible264 ASSERT_FALSE(CA(SA::Normal, SA::SM_Compatible).requiresSMChange());265 // Normal -> Streaming-compatible + LocallyStreaming266 ASSERT_FALSE(267 CA(SA::Normal, SA::SM_Compatible | SA::SM_Body).requiresSMChange());268 269 // Streaming -> Normal270 ASSERT_TRUE(CA(SA::SM_Enabled, SA::Normal).requiresSMChange());271 // Streaming -> Normal + LocallyStreaming272 ASSERT_TRUE(CA(SA::SM_Enabled, SA::Normal | SA::SM_Body).requiresSMChange());273 274 // Streaming -> Streaming275 ASSERT_FALSE(CA(SA::SM_Enabled, SA::SM_Enabled).requiresSMChange());276 // Streaming -> Streaming + LocallyStreaming277 ASSERT_FALSE(278 CA(SA::SM_Enabled, SA::SM_Enabled | SA::SM_Body).requiresSMChange());279 280 // Streaming -> Streaming-compatible281 ASSERT_FALSE(CA(SA::SM_Enabled, SA::SM_Compatible).requiresSMChange());282 // Streaming -> Streaming-compatible + LocallyStreaming283 ASSERT_FALSE(284 CA(SA::SM_Enabled, SA::SM_Compatible | SA::SM_Body).requiresSMChange());285 286 // Streaming-compatible -> Normal287 ASSERT_TRUE(CA(SA::SM_Compatible, SA::Normal).requiresSMChange());288 ASSERT_TRUE(289 CA(SA::SM_Compatible, SA::Normal | SA::SM_Body).requiresSMChange());290 291 // Streaming-compatible -> Streaming292 ASSERT_TRUE(CA(SA::SM_Compatible, SA::SM_Enabled).requiresSMChange());293 // Streaming-compatible -> Streaming + LocallyStreaming294 ASSERT_TRUE(295 CA(SA::SM_Compatible, SA::SM_Enabled | SA::SM_Body).requiresSMChange());296 297 // Streaming-compatible -> Streaming-compatible298 ASSERT_FALSE(CA(SA::SM_Compatible, SA::SM_Compatible).requiresSMChange());299 // Streaming-compatible -> Streaming-compatible + LocallyStreaming300 ASSERT_FALSE(CA(SA::SM_Compatible, SA::SM_Compatible | SA::SM_Body)301 .requiresSMChange());302 303 SA Private_ZA = SA(SA::Normal);304 SA ZA_Shared = SA(SA::encodeZAState(SA::StateValue::In));305 SA ZT0_Shared = SA(SA::encodeZT0State(SA::StateValue::In));306 SA ZA_ZT0_Shared = SA(SA::encodeZAState(SA::StateValue::In) |307 SA::encodeZT0State(SA::StateValue::In));308 SA Undef_ZT0 = SA(SA::ZT0_Undef);309 310 // Shared ZA -> Private ZA Interface311 ASSERT_FALSE(CA(ZA_Shared, Private_ZA).requiresDisablingZABeforeCall());312 ASSERT_FALSE(CA(ZA_Shared, Private_ZA).requiresEnablingZAAfterCall());313 314 // Shared ZT0 -> Private ZA Interface315 ASSERT_TRUE(CA(ZT0_Shared, Private_ZA).requiresDisablingZABeforeCall());316 ASSERT_TRUE(CA(ZT0_Shared, Private_ZA).requiresPreservingZT0());317 ASSERT_TRUE(CA(ZT0_Shared, Private_ZA).requiresEnablingZAAfterCall());318 319 // Shared Undef ZT0 -> Private ZA Interface320 // Note: "Undef ZT0" is a callsite attribute that means ZT0 is undefined at321 // point the of the call.322 ASSERT_TRUE(323 CA(ZT0_Shared, Private_ZA, Undef_ZT0).requiresDisablingZABeforeCall());324 ASSERT_FALSE(CA(ZT0_Shared, Private_ZA, Undef_ZT0).requiresPreservingZT0());325 ASSERT_TRUE(326 CA(ZT0_Shared, Private_ZA, Undef_ZT0).requiresEnablingZAAfterCall());327 328 // Shared ZA & ZT0 -> Private ZA Interface329 ASSERT_FALSE(CA(ZA_ZT0_Shared, Private_ZA).requiresDisablingZABeforeCall());330 ASSERT_TRUE(CA(ZA_ZT0_Shared, Private_ZA).requiresPreservingZT0());331 ASSERT_FALSE(CA(ZA_ZT0_Shared, Private_ZA).requiresEnablingZAAfterCall());332 333 // Shared ZA -> Shared ZA Interface334 ASSERT_FALSE(CA(ZA_Shared, ZT0_Shared).requiresDisablingZABeforeCall());335 ASSERT_FALSE(CA(ZA_Shared, ZT0_Shared).requiresEnablingZAAfterCall());336 337 // Shared ZT0 -> Shared ZA Interface338 ASSERT_FALSE(CA(ZT0_Shared, ZT0_Shared).requiresDisablingZABeforeCall());339 ASSERT_FALSE(CA(ZT0_Shared, ZT0_Shared).requiresPreservingZT0());340 ASSERT_FALSE(CA(ZT0_Shared, ZT0_Shared).requiresEnablingZAAfterCall());341 342 // Shared ZA & ZT0 -> Shared ZA Interface343 ASSERT_FALSE(CA(ZA_ZT0_Shared, ZT0_Shared).requiresDisablingZABeforeCall());344 ASSERT_FALSE(CA(ZA_ZT0_Shared, ZT0_Shared).requiresPreservingZT0());345 ASSERT_FALSE(CA(ZA_ZT0_Shared, ZT0_Shared).requiresEnablingZAAfterCall());346}347