//===- llvm/unittests/MC/AMDGPU/AMDGPUMCExprTest.cpp //---------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MCTargetDesc/AMDGPUMCExpr.h" #include "AMDGPUTargetMachine.h" #include "AMDGPUUnitTests.h" #include "GCNSubtarget.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "gtest/gtest.h" using namespace llvm; class AMDGPUMCExprTest : public AMDGPUTestBase { protected: std::unique_ptr TM; std::unique_ptr LLVMCtx; std::unique_ptr ST; std::unique_ptr MMI; std::unique_ptr MF; std::unique_ptr M; AMDGPUMCExprTest() { TM = createAMDGPUTargetMachine("amdgcn--amdpal", "gfx1010", ""); LLVMCtx = std::make_unique(); M = std::make_unique("Module", *LLVMCtx); M->setDataLayout(TM->createDataLayout()); auto *FType = FunctionType::get(Type::getVoidTy(*LLVMCtx), false); auto *F = Function::Create(FType, GlobalValue::ExternalLinkage, "Test", *M); MMI = std::make_unique(TM.get()); ST = std::make_unique(TM->getTargetTriple(), TM->getTargetCPU(), TM->getTargetFeatureString(), *TM); MF = std::make_unique(*F, *TM, *ST, MMI->getContext(), 1); } }; // Next two tests showcases the folding of foldAMDGPUMCExpr function that uses // KnownBits to simplify expressions as much as possible // max(((external_unknown & 0) | 0x8000000000000000), 5) TEST_F(AMDGPUMCExprTest, MaxFoldKnownBitsSignedness) { MCContext &Ctx = MF->getContext(); // Set up the unknown/undefined part of the expression MCSymbol *Sym = Ctx.getOrCreateSymbol("external_unknown"); const MCExpr *SymRef = MCSymbolRefExpr::create(Sym, Ctx); // Set up the rest of the expression const MCExpr *Masked = MCBinaryExpr::createAnd(SymRef, MCConstantExpr::create(0, Ctx), Ctx); const MCExpr *SignBit = AMDGPUMCExpr::createOr( {Masked, MCConstantExpr::create(INT64_MIN, Ctx)}, Ctx); const MCExpr *MaxExpr = AMDGPUMCExpr::createMax({SignBit, MCConstantExpr::create(5, Ctx)}, Ctx); // running evaluateAsAbsolute will fail since external_unknown is undefined. int64_t RuntimeRst; EXPECT_FALSE(MaxExpr->evaluateAsAbsolute(RuntimeRst)); // fold expression and then running evaluateAsAbsolute should now succeed with // the correct result const MCExpr *Folded = AMDGPU::foldAMDGPUMCExpr(MaxExpr, Ctx); int64_t FoldedVal; ASSERT_TRUE(Folded->evaluateAsAbsolute(FoldedVal)); EXPECT_EQ(FoldedVal, int64_t{5}); } // min(((external_unknown & 0) | 0x8000000000000000), 5) TEST_F(AMDGPUMCExprTest, MinFoldKnownBitsSignedness) { MCContext &Ctx = MF->getContext(); // Set up the unknown/undefined part of the expression MCSymbol *Sym = Ctx.getOrCreateSymbol("external_unknown"); const MCExpr *SymRef = MCSymbolRefExpr::create(Sym, Ctx); // Set up the rest of the expression const MCExpr *Masked = MCBinaryExpr::createAnd(SymRef, MCConstantExpr::create(0, Ctx), Ctx); const MCExpr *SignBit = AMDGPUMCExpr::createOr( {Masked, MCConstantExpr::create(INT64_MIN, Ctx)}, Ctx); const MCExpr *MinExpr = AMDGPUMCExpr::createMin({SignBit, MCConstantExpr::create(5, Ctx)}, Ctx); // running evaluateAsAbsolute will fail since external_unknown is undefined. int64_t AbsoluteRst; EXPECT_FALSE(MinExpr->evaluateAsAbsolute(AbsoluteRst)); // fold expression and then running evaluateAsAbsolute should now succeed with // the correct result const MCExpr *Folded = AMDGPU::foldAMDGPUMCExpr(MinExpr, Ctx); int64_t FoldedVal; ASSERT_TRUE(Folded->evaluateAsAbsolute(FoldedVal)); EXPECT_EQ(FoldedVal, INT64_MIN); }