3561 lines · cpp
1//===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Analysis/ValueTracking.h"10#include "llvm/ADT/FloatingPointMode.h"11#include "llvm/Analysis/AssumptionCache.h"12#include "llvm/Analysis/FloatingPointPredicateUtils.h"13#include "llvm/AsmParser/Parser.h"14#include "llvm/IR/ConstantRange.h"15#include "llvm/IR/Dominators.h"16#include "llvm/IR/Function.h"17#include "llvm/IR/IRBuilder.h"18#include "llvm/IR/InstIterator.h"19#include "llvm/IR/Instructions.h"20#include "llvm/IR/IntrinsicInst.h"21#include "llvm/IR/LLVMContext.h"22#include "llvm/IR/Module.h"23#include "llvm/Support/ErrorHandling.h"24#include "llvm/Support/KnownBits.h"25#include "llvm/Support/KnownFPClass.h"26#include "llvm/Support/SourceMgr.h"27#include "llvm/Transforms/Utils/Local.h"28#include "gtest/gtest.h"29 30using namespace llvm;31 32namespace {33 34static Instruction *findInstructionByNameOrNull(Function *F, StringRef Name) {35 for (Instruction &I : instructions(F))36 if (I.getName() == Name)37 return &I;38 39 return nullptr;40}41 42static Instruction &findInstructionByName(Function *F, StringRef Name) {43 auto *I = findInstructionByNameOrNull(F, Name);44 if (I)45 return *I;46 47 llvm_unreachable("Expected value not found");48}49 50class ValueTrackingTest : public testing::Test {51protected:52 std::unique_ptr<Module> parseModule(StringRef Assembly) {53 SMDiagnostic Error;54 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);55 56 std::string errMsg;57 raw_string_ostream os(errMsg);58 Error.print("", os);59 EXPECT_TRUE(M) << errMsg;60 61 return M;62 }63 64 void parseAssembly(StringRef Assembly) {65 M = parseModule(Assembly);66 ASSERT_TRUE(M);67 68 F = M->getFunction("test");69 ASSERT_TRUE(F) << "Test must have a function @test";70 if (!F)71 return;72 73 A = findInstructionByNameOrNull(F, "A");74 ASSERT_TRUE(A) << "@test must have an instruction %A";75 A2 = findInstructionByNameOrNull(F, "A2");76 A3 = findInstructionByNameOrNull(F, "A3");77 A4 = findInstructionByNameOrNull(F, "A4");78 A5 = findInstructionByNameOrNull(F, "A5");79 A6 = findInstructionByNameOrNull(F, "A6");80 A7 = findInstructionByNameOrNull(F, "A7");81 82 CxtI = findInstructionByNameOrNull(F, "CxtI");83 CxtI2 = findInstructionByNameOrNull(F, "CxtI2");84 CxtI3 = findInstructionByNameOrNull(F, "CxtI3");85 }86 87 LLVMContext Context;88 std::unique_ptr<Module> M;89 Function *F = nullptr;90 Instruction *A = nullptr;91 // Instructions (optional)92 Instruction *A2 = nullptr, *A3 = nullptr, *A4 = nullptr, *A5 = nullptr,93 *A6 = nullptr, *A7 = nullptr;94 95 // Context instructions (optional)96 Instruction *CxtI = nullptr, *CxtI2 = nullptr, *CxtI3 = nullptr;97};98 99class MatchSelectPatternTest : public ValueTrackingTest {100protected:101 void expectPattern(const SelectPatternResult &P) {102 Value *LHS, *RHS;103 Instruction::CastOps CastOp;104 SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);105 EXPECT_EQ(P.Flavor, R.Flavor);106 EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);107 EXPECT_EQ(P.Ordered, R.Ordered);108 }109};110 111class ComputeKnownBitsTest : public ValueTrackingTest {112protected:113 void expectKnownBits(uint64_t Zero, uint64_t One) {114 auto Known = computeKnownBits(A, M->getDataLayout());115 ASSERT_FALSE(Known.hasConflict());116 EXPECT_EQ(Known.One.getZExtValue(), One);117 EXPECT_EQ(Known.Zero.getZExtValue(), Zero);118 }119};120 121class ComputeKnownFPClassTest : public ValueTrackingTest {122protected:123 void expectKnownFPClass(unsigned KnownTrue, std::optional<bool> SignBitKnown,124 Instruction *TestVal = nullptr) {125 if (!TestVal)126 TestVal = A;127 128 KnownFPClass Known = computeKnownFPClass(TestVal, M->getDataLayout());129 EXPECT_EQ(KnownTrue, Known.KnownFPClasses);130 EXPECT_EQ(SignBitKnown, Known.SignBit);131 }132};133}134 135TEST_F(MatchSelectPatternTest, SimpleFMin) {136 parseAssembly(137 "define float @test(float %a) {\n"138 " %1 = fcmp ult float %a, 5.0\n"139 " %A = select i1 %1, float %a, float 5.0\n"140 " ret float %A\n"141 "}\n");142 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});143}144 145TEST_F(MatchSelectPatternTest, SimpleFMax) {146 parseAssembly(147 "define float @test(float %a) {\n"148 " %1 = fcmp ogt float %a, 5.0\n"149 " %A = select i1 %1, float %a, float 5.0\n"150 " ret float %A\n"151 "}\n");152 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});153}154 155TEST_F(MatchSelectPatternTest, SwappedFMax) {156 parseAssembly(157 "define float @test(float %a) {\n"158 " %1 = fcmp olt float 5.0, %a\n"159 " %A = select i1 %1, float %a, float 5.0\n"160 " ret float %A\n"161 "}\n");162 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});163}164 165TEST_F(MatchSelectPatternTest, SwappedFMax2) {166 parseAssembly(167 "define float @test(float %a) {\n"168 " %1 = fcmp olt float %a, 5.0\n"169 " %A = select i1 %1, float 5.0, float %a\n"170 " ret float %A\n"171 "}\n");172 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});173}174 175TEST_F(MatchSelectPatternTest, SwappedFMax3) {176 parseAssembly(177 "define float @test(float %a) {\n"178 " %1 = fcmp ult float %a, 5.0\n"179 " %A = select i1 %1, float 5.0, float %a\n"180 " ret float %A\n"181 "}\n");182 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});183}184 185TEST_F(MatchSelectPatternTest, FastFMin) {186 parseAssembly(187 "define float @test(float %a) {\n"188 " %1 = fcmp nnan olt float %a, 5.0\n"189 " %A = select i1 %1, float %a, float 5.0\n"190 " ret float %A\n"191 "}\n");192 expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, true});193}194 195TEST_F(MatchSelectPatternTest, FastFMinUnordered) {196 parseAssembly("define float @test(float %a) {\n"197 " %1 = fcmp nnan ult float %a, 5.0\n"198 " %A = select i1 %1, float %a, float 5.0\n"199 " ret float %A\n"200 "}\n");201 expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});202}203 204TEST_F(MatchSelectPatternTest, FMinConstantZero) {205 parseAssembly(206 "define float @test(float %a) {\n"207 " %1 = fcmp ole float %a, 0.0\n"208 " %A = select i1 %1, float %a, float 0.0\n"209 " ret float %A\n"210 "}\n");211 // This shouldn't be matched, as %a could be -0.0.212 expectPattern({SPF_UNKNOWN, SPNB_NA, false});213}214 215TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {216 parseAssembly("define float @test(float %a) {\n"217 " %1 = fcmp nsz ole float %a, 0.0\n"218 " %A = select nsz i1 %1, float %a, float 0.0\n"219 " ret float %A\n"220 "}\n");221 // But this should be, because we've ignored signed zeroes.222 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});223}224 225TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero1) {226 parseAssembly(227 "define float @test(float %a) {\n"228 " %1 = fcmp olt float -0.0, %a\n"229 " %A = select i1 %1, float 0.0, float %a\n"230 " ret float %A\n"231 "}\n");232 // The sign of zero doesn't matter in fcmp.233 expectPattern({SPF_UNKNOWN, SPNB_NA, false});234}235 236TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) {237 parseAssembly(238 "define float @test(float %a) {\n"239 " %1 = fcmp ogt float %a, -0.0\n"240 " %A = select i1 %1, float 0.0, float %a\n"241 " ret float %A\n"242 "}\n");243 // The sign of zero doesn't matter in fcmp.244 expectPattern({SPF_UNKNOWN, SPNB_NA, false});245}246 247TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) {248 parseAssembly(249 "define float @test(float %a) {\n"250 " %1 = fcmp olt float 0.0, %a\n"251 " %A = select i1 %1, float -0.0, float %a\n"252 " ret float %A\n"253 "}\n");254 // The sign of zero doesn't matter in fcmp.255 expectPattern({SPF_UNKNOWN, SPNB_NA, false});256}257 258TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) {259 parseAssembly(260 "define float @test(float %a) {\n"261 " %1 = fcmp ogt float %a, 0.0\n"262 " %A = select i1 %1, float -0.0, float %a\n"263 " ret float %A\n"264 "}\n");265 // The sign of zero doesn't matter in fcmp.266 expectPattern({SPF_UNKNOWN, SPNB_NA, false});267}268 269TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) {270 parseAssembly(271 "define float @test(float %a) {\n"272 " %1 = fcmp ogt float -0.0, %a\n"273 " %A = select i1 %1, float %a, float 0.0\n"274 " ret float %A\n"275 "}\n");276 // The sign of zero doesn't matter in fcmp.277 expectPattern({SPF_UNKNOWN, SPNB_NA, false});278}279 280TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) {281 parseAssembly(282 "define float @test(float %a) {\n"283 " %1 = fcmp olt float %a, -0.0\n"284 " %A = select i1 %1, float %a, float 0.0\n"285 " ret float %A\n"286 "}\n");287 // The sign of zero doesn't matter in fcmp.288 expectPattern({SPF_UNKNOWN, SPNB_NA, false});289}290 291TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) {292 parseAssembly(293 "define float @test(float %a) {\n"294 " %1 = fcmp ogt float 0.0, %a\n"295 " %A = select i1 %1, float %a, float -0.0\n"296 " ret float %A\n"297 "}\n");298 // The sign of zero doesn't matter in fcmp.299 expectPattern({SPF_UNKNOWN, SPNB_NA, false});300}301 302TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) {303 parseAssembly(304 "define float @test(float %a) {\n"305 " %1 = fcmp olt float %a, 0.0\n"306 " %A = select i1 %1, float %a, float -0.0\n"307 " ret float %A\n"308 "}\n");309 // The sign of zero doesn't matter in fcmp.310 expectPattern({SPF_UNKNOWN, SPNB_NA, false});311}312 313TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) {314 parseAssembly(315 "define float @test(float %a) {\n"316 " %1 = fcmp ogt float -0.0, %a\n"317 " %A = select i1 %1, float 0.0, float %a\n"318 " ret float %A\n"319 "}\n");320 // The sign of zero doesn't matter in fcmp.321 expectPattern({SPF_UNKNOWN, SPNB_NA, false});322}323 324TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) {325 parseAssembly(326 "define float @test(float %a) {\n"327 " %1 = fcmp olt float %a, -0.0\n"328 " %A = select i1 %1, float 0.0, float %a\n"329 " ret float %A\n"330 "}\n");331 // The sign of zero doesn't matter in fcmp.332 expectPattern({SPF_UNKNOWN, SPNB_NA, false});333}334 335TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) {336 parseAssembly(337 "define float @test(float %a) {\n"338 " %1 = fcmp ogt float 0.0, %a\n"339 " %A = select i1 %1, float -0.0, float %a\n"340 " ret float %A\n"341 "}\n");342 // The sign of zero doesn't matter in fcmp.343 expectPattern({SPF_UNKNOWN, SPNB_NA, false});344}345 346TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) {347 parseAssembly(348 "define float @test(float %a) {\n"349 " %1 = fcmp olt float %a, 0.0\n"350 " %A = select i1 %1, float -0.0, float %a\n"351 " ret float %A\n"352 "}\n");353 // The sign of zero doesn't matter in fcmp.354 expectPattern({SPF_UNKNOWN, SPNB_NA, false});355}356 357TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) {358 parseAssembly(359 "define float @test(float %a) {\n"360 " %1 = fcmp olt float -0.0, %a\n"361 " %A = select i1 %1, float %a, float 0.0\n"362 " ret float %A\n"363 "}\n");364 // The sign of zero doesn't matter in fcmp.365 expectPattern({SPF_UNKNOWN, SPNB_NA, false});366}367 368TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) {369 parseAssembly(370 "define float @test(float %a) {\n"371 " %1 = fcmp ogt float %a, -0.0\n"372 " %A = select i1 %1, float %a, float 0.0\n"373 " ret float %A\n"374 "}\n");375 // The sign of zero doesn't matter in fcmp.376 expectPattern({SPF_UNKNOWN, SPNB_NA, false});377}378 379TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) {380 parseAssembly(381 "define float @test(float %a) {\n"382 " %1 = fcmp olt float 0.0, %a\n"383 " %A = select i1 %1, float %a, float -0.0\n"384 " ret float %A\n"385 "}\n");386 // The sign of zero doesn't matter in fcmp.387 expectPattern({SPF_UNKNOWN, SPNB_NA, false});388}389 390TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) {391 parseAssembly(392 "define float @test(float %a) {\n"393 " %1 = fcmp ogt float %a, 0.0\n"394 " %A = select i1 %1, float %a, float -0.0\n"395 " ret float %A\n"396 "}\n");397 // The sign of zero doesn't matter in fcmp.398 expectPattern({SPF_UNKNOWN, SPNB_NA, false});399}400 401TEST_F(MatchSelectPatternTest, FMinMismatchConstantZeroVecUndef) {402 parseAssembly(403 "define <2 x float> @test(<2 x float> %a) {\n"404 " %1 = fcmp ogt <2 x float> %a, <float -0.0, float -0.0>\n"405 " %A = select <2 x i1> %1, <2 x float> <float undef, float 0.0>, <2 x float> %a\n"406 " ret <2 x float> %A\n"407 "}\n");408 // An undef in a vector constant can not be back-propagated for this analysis.409 expectPattern({SPF_UNKNOWN, SPNB_NA, false});410}411 412TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZeroVecUndef) {413 parseAssembly(414 "define <2 x float> @test(<2 x float> %a) {\n"415 " %1 = fcmp ogt <2 x float> %a, zeroinitializer\n"416 " %A = select <2 x i1> %1, <2 x float> %a, <2 x float> <float -0.0, float undef>\n"417 " ret <2 x float> %A\n"418 "}\n");419 // An undef in a vector constant can not be back-propagated for this analysis.420 expectPattern({SPF_UNKNOWN, SPNB_NA, false});421}422 423TEST_F(MatchSelectPatternTest, VectorFMinimum) {424 parseAssembly(425 "define <4 x float> @test(<4 x float> %a) {\n"426 " %1 = fcmp ule <4 x float> %a, \n"427 " <float 5.0, float 5.0, float 5.0, float 5.0>\n"428 " %A = select <4 x i1> %1, <4 x float> %a,\n"429 " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n"430 " ret <4 x float> %A\n"431 "}\n");432 // Check that pattern matching works on vectors where each lane has the same433 // unordered pattern.434 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});435}436 437TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) {438 parseAssembly(439 "define <4 x float> @test(<4 x float> %a) {\n"440 " %1 = fcmp ole <4 x float> %a, \n"441 " <float 5.0, float 5.0, float 5.0, float 5.0>\n"442 " %A = select <4 x i1> %1, <4 x float> %a,\n"443 " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n"444 " ret <4 x float> %A\n"445 "}\n");446 // Check that pattern matching works on vectors where each lane has the same447 // ordered pattern.448 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});449}450 451TEST_F(MatchSelectPatternTest, VectorNotFMinimum) {452 parseAssembly(453 "define <4 x float> @test(<4 x float> %a) {\n"454 " %1 = fcmp ule <4 x float> %a, \n"455 " <float 5.0, float 0x7ff8000000000000, float 5.0, float 5.0>\n"456 " %A = select <4 x i1> %1, <4 x float> %a,\n"457 " <4 x float> <float 5.0, float 0x7ff8000000000000, float 5.0, float "458 "5.0>\n"459 " ret <4 x float> %A\n"460 "}\n");461 // The lane that contains a NaN (0x7ff80...) behaves like a462 // non-NaN-propagating min and the other lines behave like a NaN-propagating463 // min, so check that neither is returned.464 expectPattern({SPF_UNKNOWN, SPNB_NA, false});465}466 467TEST_F(MatchSelectPatternTest, VectorNotFMinZero) {468 parseAssembly(469 "define <4 x float> @test(<4 x float> %a) {\n"470 " %1 = fcmp ule <4 x float> %a, \n"471 " <float 5.0, float -0.0, float 5.0, float 5.0>\n"472 " %A = select <4 x i1> %1, <4 x float> %a,\n"473 " <4 x float> <float 5.0, float 0.0, float 5.0, float 5.0>\n"474 " ret <4 x float> %A\n"475 "}\n");476 // Always selects the second lane of %a if it is positive or negative zero, so477 // this is stricter than a min.478 expectPattern({SPF_UNKNOWN, SPNB_NA, false});479}480 481TEST_F(MatchSelectPatternTest, DoubleCastU) {482 parseAssembly(483 "define i32 @test(i8 %a, i8 %b) {\n"484 " %1 = icmp ult i8 %a, %b\n"485 " %2 = zext i8 %a to i32\n"486 " %3 = zext i8 %b to i32\n"487 " %A = select i1 %1, i32 %2, i32 %3\n"488 " ret i32 %A\n"489 "}\n");490 // We should be able to look through the situation where we cast both operands491 // to the select.492 expectPattern({SPF_UMIN, SPNB_NA, false});493}494 495TEST_F(MatchSelectPatternTest, DoubleCastS) {496 parseAssembly(497 "define i32 @test(i8 %a, i8 %b) {\n"498 " %1 = icmp slt i8 %a, %b\n"499 " %2 = sext i8 %a to i32\n"500 " %3 = sext i8 %b to i32\n"501 " %A = select i1 %1, i32 %2, i32 %3\n"502 " ret i32 %A\n"503 "}\n");504 // We should be able to look through the situation where we cast both operands505 // to the select.506 expectPattern({SPF_SMIN, SPNB_NA, false});507}508 509TEST_F(MatchSelectPatternTest, DoubleCastBad) {510 parseAssembly(511 "define i32 @test(i8 %a, i8 %b) {\n"512 " %1 = icmp ult i8 %a, %b\n"513 " %2 = zext i8 %a to i32\n"514 " %3 = sext i8 %b to i32\n"515 " %A = select i1 %1, i32 %2, i32 %3\n"516 " ret i32 %A\n"517 "}\n");518 // The cast types here aren't the same, so we cannot match an UMIN.519 expectPattern({SPF_UNKNOWN, SPNB_NA, false});520}521 522TEST_F(MatchSelectPatternTest, NotNotSMin) {523 parseAssembly(524 "define i8 @test(i8 %a, i8 %b) {\n"525 " %cmp = icmp sgt i8 %a, %b\n"526 " %an = xor i8 %a, -1\n"527 " %bn = xor i8 %b, -1\n"528 " %A = select i1 %cmp, i8 %an, i8 %bn\n"529 " ret i8 %A\n"530 "}\n");531 expectPattern({SPF_SMIN, SPNB_NA, false});532}533 534TEST_F(MatchSelectPatternTest, NotNotSMinSwap) {535 parseAssembly(536 "define <2 x i8> @test(<2 x i8> %a, <2 x i8> %b) {\n"537 " %cmp = icmp slt <2 x i8> %a, %b\n"538 " %an = xor <2 x i8> %a, <i8 -1, i8-1>\n"539 " %bn = xor <2 x i8> %b, <i8 -1, i8-1>\n"540 " %A = select <2 x i1> %cmp, <2 x i8> %bn, <2 x i8> %an\n"541 " ret <2 x i8> %A\n"542 "}\n");543 expectPattern({SPF_SMIN, SPNB_NA, false});544}545 546TEST_F(MatchSelectPatternTest, NotNotSMax) {547 parseAssembly(548 "define i8 @test(i8 %a, i8 %b) {\n"549 " %cmp = icmp slt i8 %a, %b\n"550 " %an = xor i8 %a, -1\n"551 " %bn = xor i8 %b, -1\n"552 " %A = select i1 %cmp, i8 %an, i8 %bn\n"553 " ret i8 %A\n"554 "}\n");555 expectPattern({SPF_SMAX, SPNB_NA, false});556}557 558TEST_F(MatchSelectPatternTest, NotNotSMaxSwap) {559 parseAssembly(560 "define <2 x i8> @test(<2 x i8> %a, <2 x i8> %b) {\n"561 " %cmp = icmp sgt <2 x i8> %a, %b\n"562 " %an = xor <2 x i8> %a, <i8 -1, i8-1>\n"563 " %bn = xor <2 x i8> %b, <i8 -1, i8-1>\n"564 " %A = select <2 x i1> %cmp, <2 x i8> %bn, <2 x i8> %an\n"565 " ret <2 x i8> %A\n"566 "}\n");567 expectPattern({SPF_SMAX, SPNB_NA, false});568}569 570TEST_F(MatchSelectPatternTest, NotNotUMin) {571 parseAssembly(572 "define <2 x i8> @test(<2 x i8> %a, <2 x i8> %b) {\n"573 " %cmp = icmp ugt <2 x i8> %a, %b\n"574 " %an = xor <2 x i8> %a, <i8 -1, i8-1>\n"575 " %bn = xor <2 x i8> %b, <i8 -1, i8-1>\n"576 " %A = select <2 x i1> %cmp, <2 x i8> %an, <2 x i8> %bn\n"577 " ret <2 x i8> %A\n"578 "}\n");579 expectPattern({SPF_UMIN, SPNB_NA, false});580}581 582TEST_F(MatchSelectPatternTest, NotNotUMinSwap) {583 parseAssembly(584 "define i8 @test(i8 %a, i8 %b) {\n"585 " %cmp = icmp ult i8 %a, %b\n"586 " %an = xor i8 %a, -1\n"587 " %bn = xor i8 %b, -1\n"588 " %A = select i1 %cmp, i8 %bn, i8 %an\n"589 " ret i8 %A\n"590 "}\n");591 expectPattern({SPF_UMIN, SPNB_NA, false});592}593 594TEST_F(MatchSelectPatternTest, NotNotUMax) {595 parseAssembly(596 "define <2 x i8> @test(<2 x i8> %a, <2 x i8> %b) {\n"597 " %cmp = icmp ult <2 x i8> %a, %b\n"598 " %an = xor <2 x i8> %a, <i8 -1, i8-1>\n"599 " %bn = xor <2 x i8> %b, <i8 -1, i8-1>\n"600 " %A = select <2 x i1> %cmp, <2 x i8> %an, <2 x i8> %bn\n"601 " ret <2 x i8> %A\n"602 "}\n");603 expectPattern({SPF_UMAX, SPNB_NA, false});604}605 606TEST_F(MatchSelectPatternTest, NotNotUMaxSwap) {607 parseAssembly(608 "define i8 @test(i8 %a, i8 %b) {\n"609 " %cmp = icmp ugt i8 %a, %b\n"610 " %an = xor i8 %a, -1\n"611 " %bn = xor i8 %b, -1\n"612 " %A = select i1 %cmp, i8 %bn, i8 %an\n"613 " ret i8 %A\n"614 "}\n");615 expectPattern({SPF_UMAX, SPNB_NA, false});616}617 618TEST_F(MatchSelectPatternTest, NotNotEq) {619 parseAssembly(620 "define i8 @test(i8 %a, i8 %b) {\n"621 " %cmp = icmp eq i8 %a, %b\n"622 " %an = xor i8 %a, -1\n"623 " %bn = xor i8 %b, -1\n"624 " %A = select i1 %cmp, i8 %bn, i8 %an\n"625 " ret i8 %A\n"626 "}\n");627 expectPattern({SPF_UNKNOWN, SPNB_NA, false});628}629 630TEST_F(MatchSelectPatternTest, NotNotNe) {631 parseAssembly(632 "define i8 @test(i8 %a, i8 %b) {\n"633 " %cmp = icmp ne i8 %a, %b\n"634 " %an = xor i8 %a, -1\n"635 " %bn = xor i8 %b, -1\n"636 " %A = select i1 %cmp, i8 %bn, i8 %an\n"637 " ret i8 %A\n"638 "}\n");639 expectPattern({SPF_UNKNOWN, SPNB_NA, false});640}641 642TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) {643 StringRef Assembly =644 "declare void @nounwind_readonly(ptr) nounwind readonly "645 "declare void @nounwind_argmemonly(ptr) nounwind argmemonly "646 "declare void @nounwind_willreturn(ptr) nounwind willreturn "647 "declare void @throws_but_readonly(ptr) readonly "648 "declare void @throws_but_argmemonly(ptr) argmemonly "649 "declare void @throws_but_willreturn(ptr) willreturn "650 " "651 "declare void @unknown(ptr) "652 " "653 "define void @f(ptr %p) { "654 " call void @nounwind_readonly(ptr %p) "655 " call void @nounwind_argmemonly(ptr %p) "656 " call void @nounwind_willreturn(ptr %p)"657 " call void @throws_but_readonly(ptr %p) "658 " call void @throws_but_argmemonly(ptr %p) "659 " call void @throws_but_willreturn(ptr %p) "660 " call void @unknown(ptr %p) nounwind readonly "661 " call void @unknown(ptr %p) nounwind argmemonly "662 " call void @unknown(ptr %p) nounwind willreturn "663 " call void @unknown(ptr %p) readonly "664 " call void @unknown(ptr %p) argmemonly "665 " call void @unknown(ptr %p) willreturn "666 " ret void "667 "} ";668 669 LLVMContext Context;670 SMDiagnostic Error;671 auto M = parseAssemblyString(Assembly, Error, Context);672 assert(M && "Bad assembly?");673 674 auto *F = M->getFunction("f");675 assert(F && "Bad assembly?");676 677 auto &BB = F->getEntryBlock();678 bool ExpectedAnswers[] = {679 false, // call void @nounwind_readonly(ptr %p)680 false, // call void @nounwind_argmemonly(ptr %p)681 true, // call void @nounwind_willreturn(ptr %p)682 false, // call void @throws_but_readonly(ptr %p)683 false, // call void @throws_but_argmemonly(ptr %p)684 false, // call void @throws_but_willreturn(ptr %p)685 false, // call void @unknown(ptr %p) nounwind readonly686 false, // call void @unknown(ptr %p) nounwind argmemonly687 true, // call void @unknown(ptr %p) nounwind willreturn688 false, // call void @unknown(ptr %p) readonly689 false, // call void @unknown(ptr %p) argmemonly690 false, // call void @unknown(ptr %p) willreturn691 false, // ret void692 };693 694 int Index = 0;695 for (auto &I : BB) {696 EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I),697 ExpectedAnswers[Index])698 << "Incorrect answer at instruction " << Index << " = " << I;699 Index++;700 }701}702 703TEST_F(ValueTrackingTest, ComputeNumSignBits_PR32045) {704 parseAssembly(705 "define i32 @test(i32 %a) {\n"706 " %A = ashr i32 %a, -1\n"707 " ret i32 %A\n"708 "}\n");709 EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 32u);710}711 712// No guarantees for canonical IR in this analysis, so this just bails out.713TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle) {714 parseAssembly(715 "define <2 x i32> @test() {\n"716 " %A = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> <i32 0, i32 0>\n"717 " ret <2 x i32> %A\n"718 "}\n");719 EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);720}721 722// No guarantees for canonical IR in this analysis, so a shuffle element that723// references an undef value means this can't return any extra information.724TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle2) {725 parseAssembly(726 "define <2 x i32> @test(<2 x i1> %x) {\n"727 " %sext = sext <2 x i1> %x to <2 x i32>\n"728 " %A = shufflevector <2 x i32> %sext, <2 x i32> undef, <2 x i32> <i32 0, i32 2>\n"729 " ret <2 x i32> %A\n"730 "}\n");731 EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);732}733 734TEST_F(ValueTrackingTest, impliesPoisonTest_Identity) {735 parseAssembly("define void @test(i32 %x, i32 %y) {\n"736 " %A = add i32 %x, %y\n"737 " ret void\n"738 "}");739 EXPECT_TRUE(impliesPoison(A, A));740}741 742TEST_F(ValueTrackingTest, impliesPoisonTest_ICmp) {743 parseAssembly("define void @test(i32 %x) {\n"744 " %A2 = icmp eq i32 %x, 0\n"745 " %A = icmp eq i32 %x, 1\n"746 " ret void\n"747 "}");748 EXPECT_TRUE(impliesPoison(A2, A));749}750 751TEST_F(ValueTrackingTest, impliesPoisonTest_ICmpUnknown) {752 parseAssembly("define void @test(i32 %x, i32 %y) {\n"753 " %A2 = icmp eq i32 %x, %y\n"754 " %A = icmp eq i32 %x, 1\n"755 " ret void\n"756 "}");757 EXPECT_FALSE(impliesPoison(A2, A));758}759 760TEST_F(ValueTrackingTest, impliesPoisonTest_AddNswOkay) {761 parseAssembly("define void @test(i32 %x) {\n"762 " %A2 = add nsw i32 %x, 1\n"763 " %A = add i32 %A2, 1\n"764 " ret void\n"765 "}");766 EXPECT_TRUE(impliesPoison(A2, A));767}768 769TEST_F(ValueTrackingTest, impliesPoisonTest_AddNswOkay2) {770 parseAssembly("define void @test(i32 %x) {\n"771 " %A2 = add i32 %x, 1\n"772 " %A = add nsw i32 %A2, 1\n"773 " ret void\n"774 "}");775 EXPECT_TRUE(impliesPoison(A2, A));776}777 778TEST_F(ValueTrackingTest, impliesPoisonTest_AddNsw) {779 parseAssembly("define void @test(i32 %x) {\n"780 " %A2 = add nsw i32 %x, 1\n"781 " %A = add i32 %x, 1\n"782 " ret void\n"783 "}");784 EXPECT_FALSE(impliesPoison(A2, A));785}786 787TEST_F(ValueTrackingTest, impliesPoisonTest_Cmp) {788 parseAssembly("define void @test(i32 %x, i32 %y, i1 %c) {\n"789 " %A2 = icmp eq i32 %x, %y\n"790 " %A0 = icmp ult i32 %x, %y\n"791 " %A = or i1 %A0, %c\n"792 " ret void\n"793 "}");794 EXPECT_TRUE(impliesPoison(A2, A));795}796 797TEST_F(ValueTrackingTest, impliesPoisonTest_FCmpFMF) {798 parseAssembly("define void @test(float %x, float %y, i1 %c) {\n"799 " %A2 = fcmp nnan oeq float %x, %y\n"800 " %A0 = fcmp olt float %x, %y\n"801 " %A = or i1 %A0, %c\n"802 " ret void\n"803 "}");804 EXPECT_FALSE(impliesPoison(A2, A));805}806 807TEST_F(ValueTrackingTest, impliesPoisonTest_AddSubSameOps) {808 parseAssembly("define void @test(i32 %x, i32 %y, i1 %c) {\n"809 " %A2 = add i32 %x, %y\n"810 " %A = sub i32 %x, %y\n"811 " ret void\n"812 "}");813 EXPECT_TRUE(impliesPoison(A2, A));814}815 816TEST_F(ValueTrackingTest, impliesPoisonTest_MaskCmp) {817 parseAssembly("define void @test(i32 %x, i32 %y, i1 %c) {\n"818 " %M2 = and i32 %x, 7\n"819 " %A2 = icmp eq i32 %M2, 1\n"820 " %M = and i32 %x, 15\n"821 " %A = icmp eq i32 %M, 3\n"822 " ret void\n"823 "}");824 EXPECT_TRUE(impliesPoison(A2, A));825}826 827TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle_Pointers) {828 parseAssembly(829 "define <2 x ptr> @test(<2 x ptr> %x) {\n"830 " %A = shufflevector <2 x ptr> zeroinitializer, <2 x ptr> undef, <2 x i32> zeroinitializer\n"831 " ret <2 x ptr> %A\n"832 "}\n");833 EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 64u);834}835 836TEST(ValueTracking, propagatesPoison) {837 std::string AsmHead =838 "declare i32 @g(i32)\n"839 "define void @f(i32 %x, i32 %y, i32 %shamt, float %fx, float %fy, "840 "i1 %cond, ptr %p) {\n";841 std::string AsmTail = " ret void\n}";842 // (propagates poison?, IR instruction)843 SmallVector<std::tuple<bool, std::string, unsigned>, 32> Data = {844 {true, "add i32 %x, %y", 0},845 {true, "add i32 %x, %y", 1},846 {true, "add nsw nuw i32 %x, %y", 0},847 {true, "add nsw nuw i32 %x, %y", 1},848 {true, "ashr i32 %x, %y", 0},849 {true, "ashr i32 %x, %y", 1},850 {true, "lshr exact i32 %x, 31", 0},851 {true, "lshr exact i32 %x, 31", 1},852 {true, "fadd float %fx, %fy", 0},853 {true, "fadd float %fx, %fy", 1},854 {true, "fsub float %fx, %fy", 0},855 {true, "fsub float %fx, %fy", 1},856 {true, "fmul float %fx, %fy", 0},857 {true, "fmul float %fx, %fy", 1},858 {true, "fdiv float %fx, %fy", 0},859 {true, "fdiv float %fx, %fy", 1},860 {true, "frem float %fx, %fy", 0},861 {true, "frem float %fx, %fy", 1},862 {true, "fneg float %fx", 0},863 {true, "fcmp oeq float %fx, %fy", 0},864 {true, "fcmp oeq float %fx, %fy", 1},865 {true, "icmp eq i32 %x, %y", 0},866 {true, "icmp eq i32 %x, %y", 1},867 {true, "getelementptr i8, ptr %p, i32 %x", 0},868 {true, "getelementptr i8, ptr %p, i32 %x", 1},869 {true, "getelementptr inbounds i8, ptr %p, i32 %x", 0},870 {true, "getelementptr inbounds i8, ptr %p, i32 %x", 1},871 {true, "bitcast float %fx to i32", 0},872 {true, "select i1 %cond, i32 %x, i32 %y", 0},873 {false, "select i1 %cond, i32 %x, i32 %y", 1},874 {false, "select i1 %cond, i32 %x, i32 %y", 2},875 {false, "freeze i32 %x", 0},876 {true, "udiv i32 %x, %y", 0},877 {true, "udiv i32 %x, %y", 1},878 {true, "urem i32 %x, %y", 0},879 {true, "urem i32 %x, %y", 1},880 {true, "sdiv exact i32 %x, %y", 0},881 {true, "sdiv exact i32 %x, %y", 1},882 {true, "srem i32 %x, %y", 0},883 {true, "srem i32 %x, %y", 1},884 {false, "call i32 @g(i32 %x)", 0},885 {false, "call i32 @g(i32 %x)", 1},886 {true, "call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)", 0},887 {true, "call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %x, i32 %y)", 0},888 {true, "call {i32, i1} @llvm.smul.with.overflow.i32(i32 %x, i32 %y)", 0},889 {true, "call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)", 0},890 {true, "call {i32, i1} @llvm.usub.with.overflow.i32(i32 %x, i32 %y)", 0},891 {true, "call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 %y)", 0},892 {true, "call i32 @llvm.sadd.sat.i32(i32 %x, i32 %y)", 0},893 {true, "call i32 @llvm.ssub.sat.i32(i32 %x, i32 %y)", 0},894 {true, "call i32 @llvm.sshl.sat.i32(i32 %x, i32 %y)", 0},895 {true, "call i32 @llvm.uadd.sat.i32(i32 %x, i32 %y)", 0},896 {true, "call i32 @llvm.usub.sat.i32(i32 %x, i32 %y)", 0},897 {true, "call i32 @llvm.ushl.sat.i32(i32 %x, i32 %y)", 0},898 {true, "call i32 @llvm.ctpop.i32(i32 %x)", 0},899 {true, "call i32 @llvm.ctlz.i32(i32 %x, i1 true)", 0},900 {true, "call i32 @llvm.cttz.i32(i32 %x, i1 true)", 0},901 {true, "call i32 @llvm.abs.i32(i32 %x, i1 true)", 0},902 {true, "call i32 @llvm.smax.i32(i32 %x, i32 %y)", 0},903 {true, "call i32 @llvm.smin.i32(i32 %x, i32 %y)", 0},904 {true, "call i32 @llvm.umax.i32(i32 %x, i32 %y)", 0},905 {true, "call i32 @llvm.umin.i32(i32 %x, i32 %y)", 0},906 {true, "call i32 @llvm.bitreverse.i32(i32 %x)", 0},907 {true, "call i32 @llvm.bswap.i32(i32 %x)", 0},908 {false, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 0},909 {false, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 1},910 {false, "call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt)", 2},911 {false, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 0},912 {false, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 1},913 {false, "call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt)", 2},914 {true, "call float @llvm.sqrt.f32(float %fx)", 0},915 {true, "call float @llvm.powi.f32.i32(float %fx, i32 %x)", 0},916 {true, "call float @llvm.sin.f32(float %fx)", 0},917 {true, "call float @llvm.cos.f32(float %fx)", 0},918 {true, "call float @llvm.pow.f32(float %fx, float %fy)", 0},919 {true, "call float @llvm.exp.f32(float %fx)", 0},920 {true, "call float @llvm.exp2.f32(float %fx)", 0},921 {true, "call float @llvm.log.f32(float %fx)", 0},922 {true, "call float @llvm.log10.f32(float %fx)", 0},923 {true, "call float @llvm.log2.f32(float %fx)", 0},924 {false, "call float @llvm.fma.f32(float %fx, float %fx, float %fy)", 0},925 {false, "call float @llvm.fabs.f32(float %fx)", 0},926 {false, "call float @llvm.minnum.f32(float %fx, float %fy)", 0},927 {false, "call float @llvm.maxnum.f32(float %fx, float %fy)", 0},928 {false, "call float @llvm.minimum.f32(float %fx, float %fy)", 0},929 {false, "call float @llvm.maximum.f32(float %fx, float %fy)", 0},930 {false, "call float @llvm.copysign.f32(float %fx, float %fy)", 0},931 {true, "call float @llvm.floor.f32(float %fx)", 0},932 {true, "call float @llvm.ceil.f32(float %fx)", 0},933 {true, "call float @llvm.trunc.f32(float %fx)", 0},934 {true, "call float @llvm.rint.f32(float %fx)", 0},935 {true, "call float @llvm.nearbyint.f32(float %fx)", 0},936 {true, "call float @llvm.round.f32(float %fx)", 0},937 {true, "call float @llvm.roundeven.f32(float %fx)", 0},938 {false, "call i32 @llvm.lround.f32(float %fx)", 0},939 {false, "call i64 @llvm.llround.f32(float %fx)", 0},940 {true, "call i32 @llvm.lrint.f32(float %fx)", 0},941 {true, "call i64 @llvm.llrint.f32(float %fx)", 0},942 {false, "call float @llvm.fmuladd.f32(float %fx, float %fx, float %fy)",943 0}};944 945 std::string AssemblyStr = AsmHead;946 for (auto &Itm : Data)947 AssemblyStr += std::get<1>(Itm) + "\n";948 AssemblyStr += AsmTail;949 950 LLVMContext Context;951 SMDiagnostic Error;952 auto M = parseAssemblyString(AssemblyStr, Error, Context);953 assert(M && "Bad assembly?");954 955 auto *F = M->getFunction("f");956 assert(F && "Bad assembly?");957 958 auto &BB = F->getEntryBlock();959 960 int Index = 0;961 for (auto &I : BB) {962 if (isa<ReturnInst>(&I))963 break;964 bool ExpectedVal = std::get<0>(Data[Index]);965 unsigned OpIdx = std::get<2>(Data[Index]);966 EXPECT_EQ(propagatesPoison(I.getOperandUse(OpIdx)), ExpectedVal)967 << "Incorrect answer at instruction " << Index << " = " << I;968 Index++;969 }970}971 972TEST_F(ValueTrackingTest, programUndefinedIfPoison) {973 parseAssembly("declare i32 @any_num()"974 "define void @test(i32 %mask) {\n"975 " %A = call i32 @any_num()\n"976 " %B = or i32 %A, %mask\n"977 " udiv i32 1, %B"978 " ret void\n"979 "}\n");980 // If %A was poison, udiv raises UB regardless of %mask's value981 EXPECT_EQ(programUndefinedIfPoison(A), true);982}983 984TEST_F(ValueTrackingTest, programUndefinedIfPoisonSelect) {985 parseAssembly("declare i32 @any_num()"986 "define void @test(i1 %Cond) {\n"987 " %A = call i32 @any_num()\n"988 " %B = add i32 %A, 1\n"989 " %C = select i1 %Cond, i32 %A, i32 %B\n"990 " udiv i32 1, %C"991 " ret void\n"992 "}\n");993 // If A is poison, B is also poison, and therefore C is poison regardless of994 // the value of %Cond.995 EXPECT_EQ(programUndefinedIfPoison(A), true);996}997 998TEST_F(ValueTrackingTest, programUndefinedIfUndefOrPoison) {999 parseAssembly("declare i32 @any_num()"1000 "define void @test(i32 %mask) {\n"1001 " %A = call i32 @any_num()\n"1002 " %B = or i32 %A, %mask\n"1003 " udiv i32 1, %B"1004 " ret void\n"1005 "}\n");1006 // If %A was undef and %mask was 1, udiv does not raise UB1007 EXPECT_EQ(programUndefinedIfUndefOrPoison(A), false);1008}1009 1010TEST_F(ValueTrackingTest, isGuaranteedNotToBePoison_exploitBranchCond) {1011 parseAssembly("declare i1 @any_bool()"1012 "define void @test(i1 %y) {\n"1013 " %A = call i1 @any_bool()\n"1014 " %cond = and i1 %A, %y\n"1015 " br i1 %cond, label %BB1, label %BB2\n"1016 "BB1:\n"1017 " ret void\n"1018 "BB2:\n"1019 " ret void\n"1020 "}\n");1021 DominatorTree DT(*F);1022 for (auto &BB : *F) {1023 if (&BB == &F->getEntryBlock())1024 continue;1025 1026 EXPECT_EQ(isGuaranteedNotToBePoison(A, nullptr, BB.getTerminator(), &DT),1027 true)1028 << "isGuaranteedNotToBePoison does not hold at " << *BB.getTerminator();1029 }1030}1031 1032TEST_F(ValueTrackingTest, isGuaranteedNotToBePoison_phi) {1033 parseAssembly("declare i32 @any_i32(i32)"1034 "define void @test() {\n"1035 "ENTRY:\n"1036 " br label %LOOP\n"1037 "LOOP:\n"1038 " %A = phi i32 [0, %ENTRY], [%A.next, %NEXT]\n"1039 " %A.next = call i32 @any_i32(i32 %A)\n"1040 " %cond = icmp eq i32 %A.next, 0\n"1041 " br i1 %cond, label %NEXT, label %EXIT\n"1042 "NEXT:\n"1043 " br label %LOOP\n"1044 "EXIT:\n"1045 " ret void\n"1046 "}\n");1047 DominatorTree DT(*F);1048 for (auto &BB : *F) {1049 if (BB.getName() == "LOOP") {1050 EXPECT_EQ(isGuaranteedNotToBePoison(A, nullptr, A, &DT), true)1051 << "isGuaranteedNotToBePoison does not hold";1052 }1053 }1054}1055 1056TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison) {1057 parseAssembly("declare void @f(i32 noundef)"1058 "define void @test(i32 %x) {\n"1059 " %A = bitcast i32 %x to i32\n"1060 " call void @f(i32 noundef %x)\n"1061 " ret void\n"1062 "}\n");1063 EXPECT_EQ(isGuaranteedNotToBeUndefOrPoison(A), true);1064 EXPECT_EQ(isGuaranteedNotToBeUndefOrPoison(UndefValue::get(IntegerType::get(Context, 8))), false);1065 EXPECT_EQ(isGuaranteedNotToBeUndefOrPoison(PoisonValue::get(IntegerType::get(Context, 8))), false);1066 EXPECT_EQ(isGuaranteedNotToBePoison(UndefValue::get(IntegerType::get(Context, 8))), true);1067 EXPECT_EQ(isGuaranteedNotToBePoison(PoisonValue::get(IntegerType::get(Context, 8))), false);1068 1069 Type *Int32Ty = Type::getInt32Ty(Context);1070 Constant *CU = UndefValue::get(Int32Ty);1071 Constant *CP = PoisonValue::get(Int32Ty);1072 Constant *C1 = ConstantInt::get(Int32Ty, 1);1073 Constant *C2 = ConstantInt::get(Int32Ty, 2);1074 1075 {1076 Constant *V1 = ConstantVector::get({C1, C2});1077 EXPECT_TRUE(isGuaranteedNotToBeUndefOrPoison(V1));1078 EXPECT_TRUE(isGuaranteedNotToBePoison(V1));1079 }1080 1081 {1082 Constant *V2 = ConstantVector::get({C1, CU});1083 EXPECT_FALSE(isGuaranteedNotToBeUndefOrPoison(V2));1084 EXPECT_TRUE(isGuaranteedNotToBePoison(V2));1085 }1086 1087 {1088 Constant *V3 = ConstantVector::get({C1, CP});1089 EXPECT_FALSE(isGuaranteedNotToBeUndefOrPoison(V3));1090 EXPECT_FALSE(isGuaranteedNotToBePoison(V3));1091 }1092}1093 1094TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison_splat) {1095 parseAssembly(1096 "define <4 x i32> @test(i32 noundef %x) {\n"1097 " %ins = insertelement <4 x i32> poison, i32 %x, i32 0\n"1098 " %A = shufflevector <4 x i32> %ins, <4 x i32> poison, <4 x i32> zeroinitializer\n"1099 " ret <4 x i32> %A\n"1100 "}");1101 EXPECT_TRUE(isGuaranteedNotToBeUndefOrPoison(A));1102}1103 1104TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison_assume) {1105 parseAssembly("declare i1 @f_i1()\n"1106 "declare i32 @f_i32()\n"1107 "declare void @llvm.assume(i1)\n"1108 "define void @test() {\n"1109 " %A = call i32 @f_i32()\n"1110 " %cond = call i1 @f_i1()\n"1111 " %CxtI = add i32 0, 0\n"1112 " br i1 %cond, label %BB1, label %EXIT\n"1113 "BB1:\n"1114 " %CxtI2 = add i32 0, 0\n"1115 " %cond2 = call i1 @f_i1()\n"1116 " call void @llvm.assume(i1 true) [ \"noundef\"(i32 %A) ]\n"1117 " br i1 %cond2, label %BB2, label %EXIT\n"1118 "BB2:\n"1119 " %CxtI3 = add i32 0, 0\n"1120 " ret void\n"1121 "EXIT:\n"1122 " ret void\n"1123 "}");1124 AssumptionCache AC(*F);1125 DominatorTree DT(*F);1126 EXPECT_FALSE(isGuaranteedNotToBeUndefOrPoison(A, &AC, CxtI, &DT));1127 EXPECT_FALSE(isGuaranteedNotToBeUndefOrPoison(A, &AC, CxtI2, &DT));1128 EXPECT_TRUE(isGuaranteedNotToBeUndefOrPoison(A, &AC, CxtI3, &DT));1129}1130 1131TEST(ValueTracking, canCreatePoisonOrUndef) {1132 std::string AsmHead =1133 "@s = external dso_local global i32, align 1\n"1134 "declare i32 @g(i32)\n"1135 "declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)\n"1136 "declare {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)\n"1137 "declare {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)\n"1138 "declare {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)\n"1139 "declare {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)\n"1140 "declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)\n"1141 "define void @f(i32 %x, i32 %y, float %fx, float %fy, i1 %cond, "1142 "<4 x i32> %vx, <4 x i32> %vx2, <vscale x 4 x i32> %svx, ptr %p) {\n";1143 std::string AsmTail = " ret void\n}";1144 // (can create poison?, can create undef?, IR instruction)1145 SmallVector<std::pair<std::pair<bool, bool>, std::string>, 32> Data = {1146 {{false, false}, "add i32 %x, %y"},1147 {{true, false}, "add nsw nuw i32 %x, %y"},1148 {{true, false}, "shl i32 %x, %y"},1149 {{true, false}, "shl <4 x i32> %vx, %vx2"},1150 {{true, false}, "shl nsw i32 %x, %y"},1151 {{true, false}, "shl nsw <4 x i32> %vx, <i32 0, i32 1, i32 2, i32 3>"},1152 {{false, false}, "shl i32 %x, 31"},1153 {{true, false}, "shl i32 %x, 32"},1154 {{false, false}, "shl <4 x i32> %vx, <i32 0, i32 1, i32 2, i32 3>"},1155 {{true, false}, "shl <4 x i32> %vx, <i32 0, i32 1, i32 2, i32 32>"},1156 {{true, false}, "ashr i32 %x, %y"},1157 {{true, false}, "ashr exact i32 %x, %y"},1158 {{false, false}, "ashr i32 %x, 31"},1159 {{true, false}, "ashr exact i32 %x, 31"},1160 {{false, false}, "ashr <4 x i32> %vx, <i32 0, i32 1, i32 2, i32 3>"},1161 {{true, false}, "ashr <4 x i32> %vx, <i32 0, i32 1, i32 2, i32 32>"},1162 {{true, false}, "ashr exact <4 x i32> %vx, <i32 0, i32 1, i32 2, i32 3>"},1163 {{true, false}, "lshr i32 %x, %y"},1164 {{true, false}, "lshr exact i32 %x, 31"},1165 {{false, false}, "udiv i32 %x, %y"},1166 {{true, false}, "udiv exact i32 %x, %y"},1167 {{false, false}, "getelementptr i8, ptr %p, i32 %x"},1168 {{true, false}, "getelementptr inbounds i8, ptr %p, i32 %x"},1169 {{true, false}, "fneg nnan float %fx"},1170 {{false, false}, "fneg float %fx"},1171 {{false, false}, "fadd float %fx, %fy"},1172 {{true, false}, "fadd nnan float %fx, %fy"},1173 {{false, false}, "urem i32 %x, %y"},1174 {{true, false}, "fptoui float %fx to i32"},1175 {{true, false}, "fptosi float %fx to i32"},1176 {{false, false}, "bitcast float %fx to i32"},1177 {{false, false}, "select i1 %cond, i32 %x, i32 %y"},1178 {{true, false}, "select nnan i1 %cond, float %fx, float %fy"},1179 {{true, false}, "extractelement <4 x i32> %vx, i32 %x"},1180 {{false, false}, "extractelement <4 x i32> %vx, i32 3"},1181 {{true, false}, "extractelement <vscale x 4 x i32> %svx, i32 4"},1182 {{true, false}, "insertelement <4 x i32> %vx, i32 %x, i32 %y"},1183 {{false, false}, "insertelement <4 x i32> %vx, i32 %x, i32 3"},1184 {{true, false}, "insertelement <vscale x 4 x i32> %svx, i32 %x, i32 4"},1185 {{false, false}, "freeze i32 %x"},1186 {{false, false},1187 "shufflevector <4 x i32> %vx, <4 x i32> %vx2, "1188 "<4 x i32> <i32 0, i32 1, i32 2, i32 3>"},1189 {{true, false},1190 "shufflevector <4 x i32> %vx, <4 x i32> %vx2, "1191 "<4 x i32> <i32 0, i32 1, i32 2, i32 poison>"},1192 {{true, false},1193 "shufflevector <vscale x 4 x i32> %svx, "1194 "<vscale x 4 x i32> %svx, <vscale x 4 x i32> poison"},1195 {{true, false}, "call i32 @g(i32 %x)"},1196 {{false, false}, "call noundef i32 @g(i32 %x)"},1197 {{true, false}, "fcmp nnan oeq float %fx, %fy"},1198 {{false, false}, "fcmp oeq float %fx, %fy"},1199 {{true, false}, "ashr i32 %x, ptrtoint (ptr @s to i32)"},1200 {{false, false},1201 "call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)"},1202 {{false, false},1203 "call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %x, i32 %y)"},1204 {{false, false},1205 "call {i32, i1} @llvm.smul.with.overflow.i32(i32 %x, i32 %y)"},1206 {{false, false},1207 "call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)"},1208 {{false, false},1209 "call {i32, i1} @llvm.usub.with.overflow.i32(i32 %x, i32 %y)"},1210 {{false, false},1211 "call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 %y)"}};1212 1213 std::string AssemblyStr = AsmHead;1214 for (auto &Itm : Data)1215 AssemblyStr += Itm.second + "\n";1216 AssemblyStr += AsmTail;1217 1218 LLVMContext Context;1219 SMDiagnostic Error;1220 auto M = parseAssemblyString(AssemblyStr, Error, Context);1221 assert(M && "Bad assembly?");1222 1223 auto *F = M->getFunction("f");1224 assert(F && "Bad assembly?");1225 1226 auto &BB = F->getEntryBlock();1227 1228 int Index = 0;1229 for (auto &I : BB) {1230 if (isa<ReturnInst>(&I))1231 break;1232 bool Poison = Data[Index].first.first;1233 bool Undef = Data[Index].first.second;1234 EXPECT_EQ(canCreatePoison(cast<Operator>(&I)), Poison)1235 << "Incorrect answer of canCreatePoison at instruction " << Index1236 << " = " << I;1237 EXPECT_EQ(canCreateUndefOrPoison(cast<Operator>(&I)), Undef || Poison)1238 << "Incorrect answer of canCreateUndef at instruction " << Index1239 << " = " << I;1240 Index++;1241 }1242}1243 1244TEST_F(ValueTrackingTest, computePtrAlignment) {1245 parseAssembly("declare i1 @f_i1()\n"1246 "declare ptr @f_i8p()\n"1247 "declare void @llvm.assume(i1)\n"1248 "define void @test() {\n"1249 " %A = call ptr @f_i8p()\n"1250 " %cond = call i1 @f_i1()\n"1251 " %CxtI = add i32 0, 0\n"1252 " br i1 %cond, label %BB1, label %EXIT\n"1253 "BB1:\n"1254 " %CxtI2 = add i32 0, 0\n"1255 " %cond2 = call i1 @f_i1()\n"1256 " call void @llvm.assume(i1 true) [ \"align\"(ptr %A, i64 16) ]\n"1257 " br i1 %cond2, label %BB2, label %EXIT\n"1258 "BB2:\n"1259 " %CxtI3 = add i32 0, 0\n"1260 " ret void\n"1261 "EXIT:\n"1262 " ret void\n"1263 "}");1264 AssumptionCache AC(*F);1265 DominatorTree DT(*F);1266 const DataLayout &DL = M->getDataLayout();1267 EXPECT_EQ(getKnownAlignment(A, DL, CxtI, &AC, &DT), Align(1));1268 EXPECT_EQ(getKnownAlignment(A, DL, CxtI2, &AC, &DT), Align(1));1269 EXPECT_EQ(getKnownAlignment(A, DL, CxtI3, &AC, &DT), Align(16));1270}1271 1272TEST_F(ValueTrackingTest, MatchBinaryIntrinsicRecurrenceUMax) {1273 auto M = parseModule(R"(1274 define i8 @test(i8 %a, i8 %b) {1275 entry:1276 br label %loop1277 loop:1278 %iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]1279 %umax.acc = phi i8 [ %umax, %loop ], [ %a, %entry ]1280 %umax = call i8 @llvm.umax.i8(i8 %umax.acc, i8 %b)1281 %iv.next = add nuw i8 %iv, 11282 %cmp = icmp ult i8 %iv.next, 101283 br i1 %cmp, label %loop, label %exit1284 exit:1285 ret i8 %umax1286 }1287 )");1288 1289 auto *F = M->getFunction("test");1290 auto *II = &cast<IntrinsicInst>(findInstructionByName(F, "umax"));1291 auto *UMaxAcc = &cast<PHINode>(findInstructionByName(F, "umax.acc"));1292 PHINode *PN;1293 Value *Init, *OtherOp;1294 EXPECT_TRUE(matchSimpleBinaryIntrinsicRecurrence(II, PN, Init, OtherOp));1295 EXPECT_EQ(UMaxAcc, PN);1296 EXPECT_EQ(F->getArg(0), Init);1297 EXPECT_EQ(F->getArg(1), OtherOp);1298}1299 1300TEST_F(ValueTrackingTest, MatchBinaryIntrinsicRecurrenceNegativeFSHR) {1301 auto M = parseModule(R"(1302 define i8 @test(i8 %a, i8 %b, i8 %c) {1303 entry:1304 br label %loop1305 loop:1306 %iv = phi i8 [ %iv.next, %loop ], [ 0, %entry ]1307 %fshr.acc = phi i8 [ %fshr, %loop ], [ %a, %entry ]1308 %fshr = call i8 @llvm.fshr.i8(i8 %fshr.acc, i8 %b, i8 %c)1309 %iv.next = add nuw i8 %iv, 11310 %cmp = icmp ult i8 %iv.next, 101311 br i1 %cmp, label %loop, label %exit1312 exit:1313 ret i8 %fshr1314 }1315 )");1316 1317 auto *F = M->getFunction("test");1318 auto *II = &cast<IntrinsicInst>(findInstructionByName(F, "fshr"));1319 PHINode *PN;1320 Value *Init, *OtherOp;1321 EXPECT_FALSE(matchSimpleBinaryIntrinsicRecurrence(II, PN, Init, OtherOp));1322}1323 1324TEST_F(ComputeKnownBitsTest, ComputeKnownBits) {1325 parseAssembly(1326 "define i32 @test(i32 %a, i32 %b) {\n"1327 " %ash = mul i32 %a, 8\n"1328 " %aad = add i32 %ash, 7\n"1329 " %aan = and i32 %aad, 4095\n"1330 " %bsh = shl i32 %b, 4\n"1331 " %bad = or i32 %bsh, 6\n"1332 " %ban = and i32 %bad, 4095\n"1333 " %A = mul i32 %aan, %ban\n"1334 " ret i32 %A\n"1335 "}\n");1336 expectKnownBits(/*zero*/ 4278190085u, /*one*/ 10u);1337}1338 1339TEST_F(ComputeKnownBitsTest, ComputeKnownMulBits) {1340 parseAssembly(1341 "define i32 @test(i32 %a, i32 %b) {\n"1342 " %aa = shl i32 %a, 5\n"1343 " %bb = shl i32 %b, 5\n"1344 " %aaa = or i32 %aa, 24\n"1345 " %bbb = or i32 %bb, 28\n"1346 " %A = mul i32 %aaa, %bbb\n"1347 " ret i32 %A\n"1348 "}\n");1349 expectKnownBits(/*zero*/ 95u, /*one*/ 32u);1350}1351 1352TEST_F(ComputeKnownFPClassTest, SelectPos0) {1353 parseAssembly(1354 "define float @test(i1 %cond) {\n"1355 " %A = select i1 %cond, float 0.0, float 0.0"1356 " ret float %A\n"1357 "}\n");1358 expectKnownFPClass(fcPosZero, false);1359}1360 1361TEST_F(ComputeKnownFPClassTest, SelectNeg0) {1362 parseAssembly(1363 "define float @test(i1 %cond) {\n"1364 " %A = select i1 %cond, float -0.0, float -0.0"1365 " ret float %A\n"1366 "}\n");1367 expectKnownFPClass(fcNegZero, true);1368}1369 1370TEST_F(ComputeKnownFPClassTest, SelectPosOrNeg0) {1371 parseAssembly(1372 "define float @test(i1 %cond) {\n"1373 " %A = select i1 %cond, float 0.0, float -0.0"1374 " ret float %A\n"1375 "}\n");1376 expectKnownFPClass(fcZero, std::nullopt);1377}1378 1379TEST_F(ComputeKnownFPClassTest, SelectPosInf) {1380 parseAssembly(1381 "define float @test(i1 %cond) {\n"1382 " %A = select i1 %cond, float 0x7FF0000000000000, float 0x7FF0000000000000"1383 " ret float %A\n"1384 "}\n");1385 expectKnownFPClass(fcPosInf, false);1386}1387 1388TEST_F(ComputeKnownFPClassTest, SelectNegInf) {1389 parseAssembly(1390 "define float @test(i1 %cond) {\n"1391 " %A = select i1 %cond, float 0xFFF0000000000000, float 0xFFF0000000000000"1392 " ret float %A\n"1393 "}\n");1394 expectKnownFPClass(fcNegInf, true);1395}1396 1397TEST_F(ComputeKnownFPClassTest, SelectPosOrNegInf) {1398 parseAssembly(1399 "define float @test(i1 %cond) {\n"1400 " %A = select i1 %cond, float 0x7FF0000000000000, float 0xFFF0000000000000"1401 " ret float %A\n"1402 "}\n");1403 expectKnownFPClass(fcInf, std::nullopt);1404}1405 1406TEST_F(ComputeKnownFPClassTest, SelectNNaN) {1407 parseAssembly(1408 "define float @test(i1 %cond, float %arg0, float %arg1) {\n"1409 " %A = select nnan i1 %cond, float %arg0, float %arg1"1410 " ret float %A\n"1411 "}\n");1412 expectKnownFPClass(~fcNan, std::nullopt);1413}1414 1415TEST_F(ComputeKnownFPClassTest, SelectNInf) {1416 parseAssembly(1417 "define float @test(i1 %cond, float %arg0, float %arg1) {\n"1418 " %A = select ninf i1 %cond, float %arg0, float %arg1"1419 " ret float %A\n"1420 "}\n");1421 expectKnownFPClass(~fcInf, std::nullopt);1422}1423 1424TEST_F(ComputeKnownFPClassTest, SelectNNaNNInf) {1425 parseAssembly(1426 "define float @test(i1 %cond, float %arg0, float %arg1) {\n"1427 " %A = select nnan ninf i1 %cond, float %arg0, float %arg1"1428 " ret float %A\n"1429 "}\n");1430 expectKnownFPClass(~(fcNan | fcInf), std::nullopt);1431}1432 1433TEST_F(ComputeKnownFPClassTest, SelectNoFPClassArgUnionAll) {1434 parseAssembly(1435 "define float @test(i1 %cond, float nofpclass(snan ninf nsub pzero pnorm) %arg0, float nofpclass(qnan nnorm nzero psub pinf) %arg1) {\n"1436 " %A = select i1 %cond, float %arg0, float %arg1"1437 " ret float %A\n"1438 "}\n");1439 expectKnownFPClass(fcAllFlags, std::nullopt);1440}1441 1442TEST_F(ComputeKnownFPClassTest, SelectNoFPClassArgNoNan) {1443 parseAssembly(1444 "define float @test(i1 %cond, float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {\n"1445 " %A = select i1 %cond, float %arg0, float %arg1"1446 " ret float %A\n"1447 "}\n");1448 expectKnownFPClass(~fcNan, std::nullopt);1449}1450 1451TEST_F(ComputeKnownFPClassTest, SelectNoFPClassArgNoPInf) {1452 parseAssembly(1453 "define float @test(i1 %cond, float nofpclass(inf) %arg0, float nofpclass(pinf) %arg1) {\n"1454 " %A = select i1 %cond, float %arg0, float %arg1"1455 " ret float %A\n"1456 "}\n");1457 expectKnownFPClass(~fcPosInf, std::nullopt);1458}1459 1460TEST_F(ComputeKnownFPClassTest, SelectNoFPClassArgNoNInf) {1461 parseAssembly(1462 "define float @test(i1 %cond, float nofpclass(ninf) %arg0, float nofpclass(inf) %arg1) {\n"1463 " %A = select i1 %cond, float %arg0, float %arg1"1464 " ret float %A\n"1465 "}\n");1466 expectKnownFPClass(~fcNegInf, std::nullopt);1467}1468 1469TEST_F(ComputeKnownFPClassTest, SelectNoFPClassCallSiteNoNan) {1470 parseAssembly(1471 "declare float @func()\n"1472 "define float @test() {\n"1473 " %A = call nofpclass(nan) float @func()\n"1474 " ret float %A\n"1475 "}\n");1476 expectKnownFPClass(~fcNan, std::nullopt);1477}1478 1479TEST_F(ComputeKnownFPClassTest, SelectNoFPClassCallSiteNoZeros) {1480 parseAssembly(1481 "declare float @func()\n"1482 "define float @test() {\n"1483 " %A = call nofpclass(zero) float @func()\n"1484 " ret float %A\n"1485 "}\n");1486 expectKnownFPClass(~fcZero, std::nullopt);1487}1488 1489TEST_F(ComputeKnownFPClassTest, SelectNoFPClassDeclarationNoNan) {1490 parseAssembly(1491 "declare nofpclass(nan) float @no_nans()\n"1492 "define float @test() {\n"1493 " %A = call float @no_nans()\n"1494 " ret float %A\n"1495 "}\n");1496 expectKnownFPClass(~fcNan, std::nullopt);1497}1498 1499// Check nofpclass + ninf works on a callsite1500TEST_F(ComputeKnownFPClassTest, SelectNoFPClassCallSiteNoZerosNInfFlags) {1501 parseAssembly(1502 "declare float @func()\n"1503 "define float @test() {\n"1504 " %A = call ninf nofpclass(zero) float @func()\n"1505 " ret float %A\n"1506 "}\n");1507 expectKnownFPClass(~(fcZero | fcInf), std::nullopt);1508}1509 1510TEST_F(ComputeKnownFPClassTest, FNegNInf) {1511 parseAssembly(1512 "define float @test(float %arg) {\n"1513 " %A = fneg ninf float %arg"1514 " ret float %A\n"1515 "}\n");1516 expectKnownFPClass(~fcInf, std::nullopt);1517}1518 1519TEST_F(ComputeKnownFPClassTest, FabsUnknown) {1520 parseAssembly(1521 "declare float @llvm.fabs.f32(float)"1522 "define float @test(float %arg) {\n"1523 " %A = call float @llvm.fabs.f32(float %arg)"1524 " ret float %A\n"1525 "}\n");1526 expectKnownFPClass(fcPositive | fcNan, false);1527}1528 1529TEST_F(ComputeKnownFPClassTest, FNegFabsUnknown) {1530 parseAssembly(1531 "declare float @llvm.fabs.f32(float)"1532 "define float @test(float %arg) {\n"1533 " %fabs = call float @llvm.fabs.f32(float %arg)"1534 " %A = fneg float %fabs"1535 " ret float %A\n"1536 "}\n");1537 expectKnownFPClass(fcNegative | fcNan, true);1538}1539 1540TEST_F(ComputeKnownFPClassTest, NegFabsNInf) {1541 parseAssembly(1542 "declare float @llvm.fabs.f32(float)"1543 "define float @test(float %arg) {\n"1544 " %fabs = call ninf float @llvm.fabs.f32(float %arg)"1545 " %A = fneg float %fabs"1546 " ret float %A\n"1547 "}\n");1548 expectKnownFPClass((fcNegative & ~fcNegInf) | fcNan, true);1549}1550 1551TEST_F(ComputeKnownFPClassTest, FNegFabsNNaN) {1552 parseAssembly(1553 "declare float @llvm.fabs.f32(float)"1554 "define float @test(float %arg) {\n"1555 " %fabs = call nnan float @llvm.fabs.f32(float %arg)"1556 " %A = fneg float %fabs"1557 " ret float %A\n"1558 "}\n");1559 expectKnownFPClass(fcNegative, true);1560}1561 1562TEST_F(ComputeKnownFPClassTest, CopySignNNanSrc0) {1563 parseAssembly(1564 "declare float @llvm.fabs.f32(float)\n"1565 "declare float @llvm.copysign.f32(float, float)\n"1566 "define float @test(float %arg0, float %arg1) {\n"1567 " %fabs = call nnan float @llvm.fabs.f32(float %arg0)"1568 " %A = call float @llvm.copysign.f32(float %fabs, float %arg1)"1569 " ret float %A\n"1570 "}\n");1571 expectKnownFPClass(~fcNan, std::nullopt);1572}1573 1574TEST_F(ComputeKnownFPClassTest, CopySignNInfSrc0_NegSign) {1575 parseAssembly(1576 "declare float @llvm.log.f32(float)\n"1577 "declare float @llvm.copysign.f32(float, float)\n"1578 "define float @test(float %arg0, float %arg1) {\n"1579 " %ninf = call ninf float @llvm.log.f32(float %arg0)"1580 " %A = call float @llvm.copysign.f32(float %ninf, float -1.0)"1581 " ret float %A\n"1582 "}\n");1583 expectKnownFPClass(fcNegFinite | fcNan, true);1584}1585 1586TEST_F(ComputeKnownFPClassTest, CopySignNInfSrc0_PosSign) {1587 parseAssembly(1588 "declare float @llvm.sqrt.f32(float)\n"1589 "declare float @llvm.copysign.f32(float, float)\n"1590 "define float @test(float %arg0, float %arg1) {\n"1591 " %ninf = call ninf float @llvm.sqrt.f32(float %arg0)"1592 " %A = call float @llvm.copysign.f32(float %ninf, float 1.0)"1593 " ret float %A\n"1594 "}\n");1595 expectKnownFPClass(fcPosFinite | fcNan, false);1596}1597 1598TEST_F(ComputeKnownFPClassTest, UIToFP) {1599 parseAssembly(1600 "define float @test(i32 %arg0, i16 %arg1) {\n"1601 " %A = uitofp i32 %arg0 to float"1602 " %A2 = uitofp i16 %arg1 to half"1603 " ret float %A\n"1604 "}\n");1605 expectKnownFPClass(fcPosFinite & ~fcSubnormal, false, A);1606 expectKnownFPClass(fcPositive & ~fcSubnormal, false, A2);1607}1608 1609TEST_F(ComputeKnownFPClassTest, SIToFP) {1610 parseAssembly(1611 "define float @test(i32 %arg0, i16 %arg1, i17 %arg2) {\n"1612 " %A = sitofp i32 %arg0 to float"1613 " %A2 = sitofp i16 %arg1 to half"1614 " %A3 = sitofp i17 %arg2 to half"1615 " ret float %A\n"1616 "}\n");1617 expectKnownFPClass(fcFinite & ~fcNegZero & ~fcSubnormal, std::nullopt, A);1618 expectKnownFPClass(fcFinite & ~fcNegZero & ~fcSubnormal, std::nullopt, A2);1619 expectKnownFPClass(~(fcNan | fcNegZero | fcSubnormal), std::nullopt, A3);1620}1621 1622TEST_F(ComputeKnownFPClassTest, FAdd) {1623 parseAssembly(1624 "define float @test(float nofpclass(nan inf) %nnan.ninf, float nofpclass(nan) %nnan, float nofpclass(qnan) %no.qnan, float %unknown) {\n"1625 " %A = fadd float %nnan, %nnan.ninf"1626 " %A2 = fadd float %nnan.ninf, %nnan"1627 " %A3 = fadd float %nnan.ninf, %unknown"1628 " %A4 = fadd float %nnan.ninf, %no.qnan"1629 " %A5 = fadd float %nnan, %nnan"1630 " ret float %A\n"1631 "}\n");1632 expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);1633 expectKnownFPClass(fcFinite | fcInf, std::nullopt, A2);1634 expectKnownFPClass(fcAllFlags, std::nullopt, A3);1635 expectKnownFPClass(fcAllFlags, std::nullopt, A4);1636 expectKnownFPClass(fcAllFlags, std::nullopt, A5);1637}1638 1639TEST_F(ComputeKnownFPClassTest, FSub) {1640 parseAssembly(1641 "define float @test(float nofpclass(nan inf) %nnan.ninf, float nofpclass(nan) %nnan, float nofpclass(qnan) %no.qnan, float %unknown) {\n"1642 " %A = fsub float %nnan, %nnan.ninf"1643 " %A2 = fsub float %nnan.ninf, %nnan"1644 " %A3 = fsub float %nnan.ninf, %unknown"1645 " %A4 = fsub float %nnan.ninf, %no.qnan"1646 " %A5 = fsub float %nnan, %nnan"1647 " ret float %A\n"1648 "}\n");1649 expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);1650 expectKnownFPClass(fcFinite | fcInf, std::nullopt, A2);1651 expectKnownFPClass(fcAllFlags, std::nullopt, A3);1652 expectKnownFPClass(fcAllFlags, std::nullopt, A4);1653 expectKnownFPClass(fcAllFlags, std::nullopt, A5);1654}1655 1656TEST_F(ComputeKnownFPClassTest, FMul) {1657 parseAssembly(1658 "define float @test(float nofpclass(nan inf) %nnan.ninf0, float nofpclass(nan inf) %nnan.ninf1, float nofpclass(nan) %nnan, float nofpclass(qnan) %no.qnan, float %unknown) {\n"1659 " %A = fmul float %nnan.ninf0, %nnan.ninf1"1660 " %A2 = fmul float %nnan.ninf0, %nnan"1661 " %A3 = fmul float %nnan, %nnan.ninf0"1662 " %A4 = fmul float %nnan.ninf0, %no.qnan"1663 " %A5 = fmul float %nnan, %nnan"1664 " ret float %A\n"1665 "}\n");1666 expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);1667 expectKnownFPClass(fcAllFlags, std::nullopt, A2);1668 expectKnownFPClass(fcAllFlags, std::nullopt, A3);1669 expectKnownFPClass(fcAllFlags, std::nullopt, A4);1670 expectKnownFPClass(fcPositive | fcNan, std::nullopt, A5);1671}1672 1673TEST_F(ComputeKnownFPClassTest, FMulNoZero) {1674 parseAssembly(1675 "define float @test(float nofpclass(zero) %no.zero, float nofpclass(zero nan) %no.zero.nan0, float nofpclass(zero nan) %no.zero.nan1, float nofpclass(nzero nan) %no.negzero.nan, float nofpclass(pzero nan) %no.poszero.nan, float nofpclass(inf nan) %no.inf.nan, float nofpclass(inf) %no.inf, float nofpclass(nan) %no.nan) {\n"1676 " %A = fmul float %no.zero.nan0, %no.zero.nan1"1677 " %A2 = fmul float %no.zero, %no.zero"1678 " %A3 = fmul float %no.poszero.nan, %no.zero.nan0"1679 " %A4 = fmul float %no.nan, %no.zero"1680 " %A5 = fmul float %no.zero, %no.inf"1681 " %A6 = fmul float %no.zero.nan0, %no.nan"1682 " %A7 = fmul float %no.nan, %no.zero.nan0"1683 " ret float %A\n"1684 "}\n");1685 expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);1686 expectKnownFPClass(fcPositive | fcNan, std::nullopt, A2);1687 expectKnownFPClass(fcAllFlags, std::nullopt, A3);1688 expectKnownFPClass(fcAllFlags, std::nullopt, A4);1689 expectKnownFPClass(fcAllFlags, std::nullopt, A5);1690 expectKnownFPClass(fcAllFlags, std::nullopt, A6);1691 expectKnownFPClass(fcAllFlags, std::nullopt, A7);1692}1693 1694TEST_F(ComputeKnownFPClassTest, MinimumNumSignBit) {1695 parseAssembly(1696 R"(1697 define float @test(1698 float %unknown,1699 float nofpclass(nan) %nnan,1700 float nofpclass(nan pinf pnorm psub pzero) %nnan.nopos,1701 float nofpclass(nan ninf nnorm nsub nzero) %nnan.noneg,1702 float nofpclass(ninf nnorm nsub nzero) %noneg,1703 float nofpclass(pinf pnorm psub pzero) %nopos) {1704 %A = call float @llvm.minimumnum.f32(float %nnan.nopos, float %unknown)1705 %A2 = call float @llvm.minimumnum.f32(float %unknown, float %nnan.nopos)1706 %A3 = call float @llvm.minimumnum.f32(float %nnan.noneg, float %unknown)1707 %A4 = call float @llvm.minimumnum.f32(float %unknown, float %nnan.noneg)1708 %A5 = call float @llvm.minimumnum.f32(float %nnan.nopos, float %nnan.noneg)1709 %A6 = call float @llvm.minimumnum.f32(float %nopos, float %nnan.noneg)1710 %A7 = call float @llvm.minimumnum.f32(float %nnan.nopos, float %noneg)1711 ret float %A1712 })");1713 expectKnownFPClass(fcNegative, true, A);1714 expectKnownFPClass(fcNegative, true, A2);1715 expectKnownFPClass(~fcNan, std::nullopt, A3);1716 expectKnownFPClass(~fcNan, std::nullopt, A4);1717 expectKnownFPClass(fcNegative, true, A5);1718 expectKnownFPClass(~fcNan, std::nullopt, A6);1719 expectKnownFPClass(fcNegative, true, A7);1720}1721 1722TEST_F(ComputeKnownFPClassTest, MaximumNumSignBit) {1723 parseAssembly(1724 R"(1725 define float @test(1726 float %unknown,1727 float nofpclass(nan) %nnan,1728 float nofpclass(nan pinf pnorm psub pzero) %nnan.nopos,1729 float nofpclass(nan ninf nnorm nsub nzero) %nnan.noneg,1730 float nofpclass(ninf nnorm nsub nzero) %noneg,1731 float nofpclass(pinf pnorm psub pzero) %nopos) {1732 %A = call float @llvm.maximumnum.f32(float %nnan.noneg, float %unknown)1733 %A2 = call float @llvm.maximumnum.f32(float %unknown, float %nnan.noneg)1734 %A3 = call float @llvm.maximumnum.f32(float %nnan.nopos, float %unknown)1735 %A4 = call float @llvm.maximumnum.f32(float %unknown, float %nnan.nopos)1736 %A5 = call float @llvm.maximumnum.f32(float %nnan.noneg, float %nnan.nopos)1737 %A6 = call float @llvm.maximumnum.f32(float %noneg, float %nnan.nopos)1738 %A7 = call float @llvm.maximumnum.f32(float %nnan.noneg, float %nopos)1739 ret float %A1740 })");1741 expectKnownFPClass(fcPositive, false, A);1742 expectKnownFPClass(fcPositive, false, A2);1743 expectKnownFPClass(~fcNan, std::nullopt, A3);1744 expectKnownFPClass(~fcNan, std::nullopt, A4);1745 expectKnownFPClass(fcPositive, false, A5);1746 expectKnownFPClass(~fcNan, std::nullopt, A6);1747 expectKnownFPClass(fcPositive, false, A7);1748}1749 1750TEST_F(ComputeKnownFPClassTest, Phi) {1751 parseAssembly(1752 "define float @test(i1 %cond, float nofpclass(nan inf) %arg0, float nofpclass(nan) %arg1) {\n"1753 "entry:\n"1754 " br i1 %cond, label %bb0, label %bb1\n"1755 "bb0:\n"1756 " br label %ret\n"1757 "bb1:\n"1758 " br label %ret\n"1759 "ret:\n"1760 " %A = phi float [ %arg0, %bb0 ], [ %arg1, %bb1 ]\n"1761 " ret float %A\n"1762 "}\n");1763 expectKnownFPClass(~fcNan, std::nullopt);1764}1765 1766TEST_F(ComputeKnownFPClassTest, PhiKnownSignFalse) {1767 parseAssembly(1768 "declare float @llvm.fabs.f32(float)"1769 "define float @test(i1 %cond, float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {\n"1770 "entry:\n"1771 " br i1 %cond, label %bb0, label %bb1\n"1772 "bb0:\n"1773 " %fabs.arg0 = call float @llvm.fabs.f32(float %arg0)\n"1774 " br label %ret\n"1775 "bb1:\n"1776 " %fabs.arg1 = call float @llvm.fabs.f32(float %arg1)\n"1777 " br label %ret\n"1778 "ret:\n"1779 " %A = phi float [ %fabs.arg0, %bb0 ], [ %fabs.arg1, %bb1 ]\n"1780 " ret float %A\n"1781 "}\n");1782 expectKnownFPClass(fcPositive, false);1783}1784 1785TEST_F(ComputeKnownFPClassTest, PhiKnownSignTrue) {1786 parseAssembly(1787 "declare float @llvm.fabs.f32(float)"1788 "define float @test(i1 %cond, float nofpclass(nan) %arg0, float %arg1) {\n"1789 "entry:\n"1790 " br i1 %cond, label %bb0, label %bb1\n"1791 "bb0:\n"1792 " %fabs.arg0 = call float @llvm.fabs.f32(float %arg0)\n"1793 " %fneg.fabs.arg0 = fneg float %fabs.arg0\n"1794 " br label %ret\n"1795 "bb1:\n"1796 " %fabs.arg1 = call float @llvm.fabs.f32(float %arg1)\n"1797 " %fneg.fabs.arg1 = fneg float %fabs.arg1\n"1798 " br label %ret\n"1799 "ret:\n"1800 " %A = phi float [ %fneg.fabs.arg0, %bb0 ], [ %fneg.fabs.arg1, %bb1 ]\n"1801 " ret float %A\n"1802 "}\n");1803 expectKnownFPClass(fcNegative | fcNan, true);1804}1805 1806TEST_F(ComputeKnownFPClassTest, UnreachablePhi) {1807 parseAssembly(1808 "define float @test(float %arg) {\n"1809 "entry:\n"1810 " ret float 0.0\n"1811 "unreachable:\n"1812 " %A = phi float\n"1813 " ret float %A\n"1814 "}\n");1815 expectKnownFPClass(fcAllFlags, std::nullopt);1816}1817 1818TEST_F(ComputeKnownFPClassTest, SelfPhiOnly) {1819 parseAssembly(1820 "define float @test(float %arg) {\n"1821 "entry:\n"1822 " ret float 0.0\n"1823 "loop:\n"1824 " %A = phi float [ %A, %loop ]\n"1825 " br label %loop\n"1826 "}\n");1827 expectKnownFPClass(fcAllFlags, std::nullopt);1828}1829 1830TEST_F(ComputeKnownFPClassTest, SelfPhiFirstArg) {1831 parseAssembly(1832 "define float @test(i1 %cond, float nofpclass(inf) %arg) {\n"1833 "entry:\n"1834 " br i1 %cond, label %loop, label %ret\n"1835 "loop:\n"1836 " %A = phi float [ %arg, %entry ], [ %A, %loop ]\n"1837 " br label %loop\n"1838 "ret:\n"1839 " ret float %A"1840 "}\n");1841 expectKnownFPClass(~fcInf, std::nullopt);1842}1843 1844TEST_F(ComputeKnownFPClassTest, SelfPhiSecondArg) {1845 parseAssembly(1846 "define float @test(i1 %cond, float nofpclass(inf) %arg) {\n"1847 "entry:\n"1848 " br i1 %cond, label %loop, label %ret\n"1849 "loop:\n"1850 " %A = phi float [ %A, %loop ], [ %arg, %entry ]\n"1851 " br label %loop\n"1852 "ret:\n"1853 " ret float %A"1854 "}\n");1855 expectKnownFPClass(~fcInf, std::nullopt);1856}1857 1858TEST_F(ComputeKnownFPClassTest, CannotBeOrderedLessThanZero) {1859 parseAssembly("define float @test(float %arg) {\n"1860 " %A = fmul float %arg, %arg"1861 " ret float %A\n"1862 "}\n");1863 1864 Type *FPTy = Type::getDoubleTy(M->getContext());1865 const DataLayout &DL = M->getDataLayout();1866 1867 EXPECT_TRUE(1868 computeKnownFPClass(ConstantFP::getZero(FPTy, /*Negative=*/false), DL)1869 .cannotBeOrderedLessThanZero());1870 EXPECT_TRUE(1871 computeKnownFPClass(ConstantFP::getZero(FPTy, /*Negative=*/true), DL)1872 .cannotBeOrderedLessThanZero());1873 1874 EXPECT_TRUE(computeKnownFPClass(ConstantFP::getInfinity(FPTy, false), DL)1875 .cannotBeOrderedLessThanZero());1876 EXPECT_FALSE(computeKnownFPClass(ConstantFP::getInfinity(FPTy, true), DL)1877 .cannotBeOrderedLessThanZero());1878 1879 EXPECT_TRUE(computeKnownFPClass(ConstantFP::get(FPTy, 1.0), DL)1880 .cannotBeOrderedLessThanZero());1881 EXPECT_FALSE(computeKnownFPClass(ConstantFP::get(FPTy, -1.0), DL)1882 .cannotBeOrderedLessThanZero());1883 1884 EXPECT_TRUE(1885 computeKnownFPClass(1886 ConstantFP::get(FPTy, APFloat::getSmallest(FPTy->getFltSemantics(),1887 /*Negative=*/false)),1888 DL)1889 .cannotBeOrderedLessThanZero());1890 EXPECT_FALSE(1891 computeKnownFPClass(1892 ConstantFP::get(FPTy, APFloat::getSmallest(FPTy->getFltSemantics(),1893 /*Negative=*/true)),1894 DL)1895 .cannotBeOrderedLessThanZero());1896 1897 EXPECT_TRUE(1898 computeKnownFPClass(ConstantFP::getQNaN(FPTy, /*Negative=*/false), DL)1899 .cannotBeOrderedLessThanZero());1900 EXPECT_TRUE(1901 computeKnownFPClass(ConstantFP::getQNaN(FPTy, /*Negative=*/true), DL)1902 .cannotBeOrderedLessThanZero());1903 EXPECT_TRUE(1904 computeKnownFPClass(ConstantFP::getSNaN(FPTy, /*Negative=*/false), DL)1905 .cannotBeOrderedLessThanZero());1906 EXPECT_TRUE(1907 computeKnownFPClass(ConstantFP::getSNaN(FPTy, /*Negative=*/true), DL)1908 .cannotBeOrderedLessThanZero());1909}1910 1911TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_OrdNan) {1912 parseAssembly("define i1 @test(double %arg) {\n"1913 " %A = fcmp ord double %arg, 0x7FF8000000000000"1914 " %A2 = fcmp uno double %arg, 0x7FF8000000000000"1915 " %A3 = fcmp oeq double %arg, 0x7FF8000000000000"1916 " %A4 = fcmp ueq double %arg, 0x7FF8000000000000"1917 " ret i1 %A\n"1918 "}\n");1919 1920 auto [OrdVal, OrdClass] = fcmpToClassTest(1921 CmpInst::FCMP_ORD, *A->getFunction(), A->getOperand(0), A->getOperand(1));1922 EXPECT_EQ(A->getOperand(0), OrdVal);1923 EXPECT_EQ(fcNone, OrdClass);1924 1925 auto [UnordVal, UnordClass] =1926 fcmpToClassTest(CmpInst::FCMP_UNO, *A2->getFunction(), A2->getOperand(0),1927 A2->getOperand(1));1928 EXPECT_EQ(A2->getOperand(0), UnordVal);1929 EXPECT_EQ(fcAllFlags, UnordClass);1930 1931 auto [OeqVal, OeqClass] =1932 fcmpToClassTest(CmpInst::FCMP_OEQ, *A3->getFunction(), A3->getOperand(0),1933 A3->getOperand(1));1934 EXPECT_EQ(A3->getOperand(0), OeqVal);1935 EXPECT_EQ(fcNone, OeqClass);1936 1937 auto [UeqVal, UeqClass] =1938 fcmpToClassTest(CmpInst::FCMP_UEQ, *A3->getFunction(), A3->getOperand(0),1939 A3->getOperand(1));1940 EXPECT_EQ(A3->getOperand(0), UeqVal);1941 EXPECT_EQ(fcAllFlags, UeqClass);1942}1943 1944TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_NInf) {1945 parseAssembly("define i1 @test(double %arg) {\n"1946 " %A = fcmp olt double %arg, 0xFFF0000000000000"1947 " %A2 = fcmp uge double %arg, 0xFFF0000000000000"1948 " %A3 = fcmp ogt double %arg, 0xFFF0000000000000"1949 " %A4 = fcmp ule double %arg, 0xFFF0000000000000"1950 " %A5 = fcmp oge double %arg, 0xFFF0000000000000"1951 " %A6 = fcmp ult double %arg, 0xFFF0000000000000"1952 " ret i1 %A\n"1953 "}\n");1954 1955 auto [OltVal, OltClass] = fcmpToClassTest(1956 CmpInst::FCMP_OLT, *A->getFunction(), A->getOperand(0), A->getOperand(1));1957 EXPECT_EQ(A->getOperand(0), OltVal);1958 EXPECT_EQ(fcNone, OltClass);1959 1960 auto [UgeVal, UgeClass] =1961 fcmpToClassTest(CmpInst::FCMP_UGE, *A2->getFunction(), A2->getOperand(0),1962 A2->getOperand(1));1963 EXPECT_EQ(A2->getOperand(0), UgeVal);1964 EXPECT_EQ(fcAllFlags, UgeClass);1965 1966 auto [OgtVal, OgtClass] =1967 fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0),1968 A3->getOperand(1));1969 EXPECT_EQ(A3->getOperand(0), OgtVal);1970 EXPECT_EQ(~(fcNegInf | fcNan), OgtClass);1971 1972 auto [UleVal, UleClass] =1973 fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0),1974 A4->getOperand(1));1975 EXPECT_EQ(A4->getOperand(0), UleVal);1976 EXPECT_EQ(fcNegInf | fcNan, UleClass);1977 1978 auto [OgeVal, OgeClass] =1979 fcmpToClassTest(CmpInst::FCMP_OGE, *A5->getFunction(), A5->getOperand(0),1980 A5->getOperand(1));1981 EXPECT_EQ(A5->getOperand(0), OgeVal);1982 EXPECT_EQ(~fcNan, OgeClass);1983 1984 auto [UltVal, UltClass] =1985 fcmpToClassTest(CmpInst::FCMP_ULT, *A6->getFunction(), A6->getOperand(0),1986 A6->getOperand(1));1987 EXPECT_EQ(A6->getOperand(0), UltVal);1988 EXPECT_EQ(fcNan, UltClass);1989}1990 1991TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_FabsNInf) {1992 parseAssembly("declare double @llvm.fabs.f64(double)\n"1993 "define i1 @test(double %arg) {\n"1994 " %fabs.arg = call double @llvm.fabs.f64(double %arg)\n"1995 " %A = fcmp olt double %fabs.arg, 0xFFF0000000000000"1996 " %A2 = fcmp uge double %fabs.arg, 0xFFF0000000000000"1997 " %A3 = fcmp ogt double %fabs.arg, 0xFFF0000000000000"1998 " %A4 = fcmp ule double %fabs.arg, 0xFFF0000000000000"1999 " %A5 = fcmp oge double %fabs.arg, 0xFFF0000000000000"2000 " %A6 = fcmp ult double %fabs.arg, 0xFFF0000000000000"2001 " ret i1 %A\n"2002 "}\n");2003 2004 Value *ArgVal = F->getArg(0);2005 2006 auto [OltVal, OltClass] = fcmpToClassTest(2007 CmpInst::FCMP_OLT, *A->getFunction(), A->getOperand(0), A->getOperand(1));2008 EXPECT_EQ(ArgVal, OltVal);2009 EXPECT_EQ(fcNone, OltClass);2010 2011 auto [UgeVal, UgeClass] =2012 fcmpToClassTest(CmpInst::FCMP_UGE, *A2->getFunction(), A2->getOperand(0),2013 A2->getOperand(1));2014 EXPECT_EQ(ArgVal, UgeVal);2015 EXPECT_EQ(fcAllFlags, UgeClass);2016 2017 auto [OgtVal, OgtClass] =2018 fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0),2019 A3->getOperand(1));2020 EXPECT_EQ(ArgVal, OgtVal);2021 EXPECT_EQ(~fcNan, OgtClass);2022 2023 auto [UleVal, UleClass] =2024 fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0),2025 A4->getOperand(1));2026 EXPECT_EQ(ArgVal, UleVal);2027 EXPECT_EQ(fcNan, UleClass);2028 2029 auto [OgeVal, OgeClass] =2030 fcmpToClassTest(CmpInst::FCMP_OGE, *A5->getFunction(), A5->getOperand(0),2031 A5->getOperand(1));2032 EXPECT_EQ(ArgVal, OgeVal);2033 EXPECT_EQ(~fcNan, OgeClass);2034 2035 auto [UltVal, UltClass] =2036 fcmpToClassTest(CmpInst::FCMP_ULT, *A6->getFunction(), A6->getOperand(0),2037 A6->getOperand(1));2038 EXPECT_EQ(ArgVal, UltVal);2039 EXPECT_EQ(fcNan, UltClass);2040}2041 2042TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_PInf) {2043 parseAssembly("define i1 @test(double %arg) {\n"2044 " %A = fcmp ogt double %arg, 0x7FF0000000000000"2045 " %A2 = fcmp ule double %arg, 0x7FF0000000000000"2046 " %A3 = fcmp ole double %arg, 0x7FF0000000000000"2047 " %A4 = fcmp ugt double %arg, 0x7FF0000000000000"2048 " ret i1 %A\n"2049 "}\n");2050 2051 auto [OgtVal, OgtClass] = fcmpToClassTest(2052 CmpInst::FCMP_OGT, *A->getFunction(), A->getOperand(0), A->getOperand(1));2053 EXPECT_EQ(A->getOperand(0), OgtVal);2054 EXPECT_EQ(fcNone, OgtClass);2055 2056 auto [UleVal, UleClass] =2057 fcmpToClassTest(CmpInst::FCMP_ULE, *A2->getFunction(), A2->getOperand(0),2058 A2->getOperand(1));2059 EXPECT_EQ(A2->getOperand(0), UleVal);2060 EXPECT_EQ(fcAllFlags, UleClass);2061 2062 auto [OleVal, OleClass] =2063 fcmpToClassTest(CmpInst::FCMP_OLE, *A3->getFunction(), A3->getOperand(0),2064 A3->getOperand(1));2065 EXPECT_EQ(A->getOperand(0), OleVal);2066 EXPECT_EQ(~fcNan, OleClass);2067 2068 auto [UgtVal, UgtClass] =2069 fcmpToClassTest(CmpInst::FCMP_UGT, *A4->getFunction(), A4->getOperand(0),2070 A4->getOperand(1));2071 EXPECT_EQ(A4->getOperand(0), UgtVal);2072 EXPECT_EQ(fcNan, UgtClass);2073}2074 2075TEST_F(ComputeKnownFPClassTest, SqrtNszSignBit) {2076 parseAssembly(2077 "declare float @llvm.sqrt.f32(float)\n"2078 "define float @test(float %arg, float nofpclass(nan) %arg.nnan) {\n"2079 " %A = call float @llvm.sqrt.f32(float %arg)\n"2080 " %A2 = call nsz float @llvm.sqrt.f32(float %arg)\n"2081 " %A3 = call float @llvm.sqrt.f32(float %arg.nnan)\n"2082 " %A4 = call nsz float @llvm.sqrt.f32(float %arg.nnan)\n"2083 " ret float %A\n"2084 "}\n");2085 2086 const FPClassTest SqrtMask = fcPositive | fcNegZero | fcNan;2087 const FPClassTest NszSqrtMask = fcPositive | fcNan;2088 2089 {2090 KnownFPClass UseInstrInfo =2091 computeKnownFPClass(A, M->getDataLayout(), fcAllFlags, nullptr, nullptr,2092 nullptr, nullptr, /*UseInstrInfo=*/true);2093 EXPECT_EQ(SqrtMask, UseInstrInfo.KnownFPClasses);2094 EXPECT_EQ(std::nullopt, UseInstrInfo.SignBit);2095 2096 KnownFPClass NoUseInstrInfo =2097 computeKnownFPClass(A, M->getDataLayout(), fcAllFlags, nullptr, nullptr,2098 nullptr, nullptr, /*UseInstrInfo=*/false);2099 EXPECT_EQ(SqrtMask, NoUseInstrInfo.KnownFPClasses);2100 EXPECT_EQ(std::nullopt, NoUseInstrInfo.SignBit);2101 }2102 2103 {2104 KnownFPClass UseInstrInfoNSZ =2105 computeKnownFPClass(A2, M->getDataLayout(), fcAllFlags, nullptr,2106 nullptr, nullptr, nullptr, /*UseInstrInfo=*/true);2107 EXPECT_EQ(NszSqrtMask, UseInstrInfoNSZ.KnownFPClasses);2108 EXPECT_EQ(std::nullopt, UseInstrInfoNSZ.SignBit);2109 2110 KnownFPClass NoUseInstrInfoNSZ =2111 computeKnownFPClass(A2, M->getDataLayout(), fcAllFlags, nullptr,2112 nullptr, nullptr, nullptr, /*UseInstrInfo=*/false);2113 EXPECT_EQ(SqrtMask, NoUseInstrInfoNSZ.KnownFPClasses);2114 EXPECT_EQ(std::nullopt, NoUseInstrInfoNSZ.SignBit);2115 }2116 2117 {2118 KnownFPClass UseInstrInfoNoNan =2119 computeKnownFPClass(A3, M->getDataLayout(), fcAllFlags, nullptr,2120 nullptr, nullptr, nullptr, /*UseInstrInfo=*/true);2121 EXPECT_EQ(fcPositive | fcNegZero | fcQNan,2122 UseInstrInfoNoNan.KnownFPClasses);2123 EXPECT_EQ(std::nullopt, UseInstrInfoNoNan.SignBit);2124 2125 KnownFPClass NoUseInstrInfoNoNan =2126 computeKnownFPClass(A3, M->getDataLayout(), fcAllFlags, nullptr,2127 nullptr, nullptr, nullptr, /*UseInstrInfo=*/false);2128 EXPECT_EQ(fcPositive | fcNegZero | fcQNan,2129 NoUseInstrInfoNoNan.KnownFPClasses);2130 EXPECT_EQ(std::nullopt, NoUseInstrInfoNoNan.SignBit);2131 }2132 2133 {2134 KnownFPClass UseInstrInfoNSZNoNan =2135 computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, nullptr,2136 nullptr, nullptr, nullptr, /*UseInstrInfo=*/true);2137 EXPECT_EQ(fcPositive | fcQNan, UseInstrInfoNSZNoNan.KnownFPClasses);2138 EXPECT_EQ(std::nullopt, UseInstrInfoNSZNoNan.SignBit);2139 2140 KnownFPClass NoUseInstrInfoNSZNoNan =2141 computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, nullptr,2142 nullptr, nullptr, nullptr, /*UseInstrInfo=*/false);2143 EXPECT_EQ(fcPositive | fcNegZero | fcQNan,2144 NoUseInstrInfoNSZNoNan.KnownFPClasses);2145 EXPECT_EQ(std::nullopt, NoUseInstrInfoNSZNoNan.SignBit);2146 }2147}2148 2149TEST_F(ComputeKnownFPClassTest, Constants) {2150 parseAssembly("declare float @func()\n"2151 "define float @test() {\n"2152 " %A = call float @func()\n"2153 " ret float %A\n"2154 "}\n");2155 2156 Type *F32 = Type::getFloatTy(Context);2157 Type *V4F32 = FixedVectorType::get(F32, 4);2158 2159 {2160 KnownFPClass ConstAggZero = computeKnownFPClass(2161 ConstantAggregateZero::get(V4F32), M->getDataLayout(), fcAllFlags);2162 2163 EXPECT_EQ(fcPosZero, ConstAggZero.KnownFPClasses);2164 ASSERT_TRUE(ConstAggZero.SignBit);2165 EXPECT_FALSE(*ConstAggZero.SignBit);2166 }2167 2168 {2169 KnownFPClass Undef = computeKnownFPClass(UndefValue::get(F32),2170 M->getDataLayout(), fcAllFlags);2171 EXPECT_EQ(fcAllFlags, Undef.KnownFPClasses);2172 EXPECT_FALSE(Undef.SignBit);2173 }2174 2175 {2176 KnownFPClass Poison = computeKnownFPClass(PoisonValue::get(F32),2177 M->getDataLayout(), fcAllFlags);2178 EXPECT_EQ(fcNone, Poison.KnownFPClasses);2179 ASSERT_TRUE(Poison.SignBit);2180 EXPECT_FALSE(*Poison.SignBit);2181 }2182 2183 {2184 // Assume the poison element should be 0.2185 Constant *ZeroF32 = ConstantFP::getZero(F32);2186 Constant *PoisonF32 = PoisonValue::get(F32);2187 2188 KnownFPClass PartiallyPoison =2189 computeKnownFPClass(ConstantVector::get({ZeroF32, PoisonF32}),2190 M->getDataLayout(), fcAllFlags);2191 EXPECT_EQ(fcPosZero, PartiallyPoison.KnownFPClasses);2192 ASSERT_TRUE(PartiallyPoison.SignBit);2193 EXPECT_FALSE(*PartiallyPoison.SignBit);2194 }2195 2196 {2197 // Assume the poison element should be 1.2198 Constant *NegZeroF32 = ConstantFP::getZero(F32, true);2199 Constant *PoisonF32 = PoisonValue::get(F32);2200 2201 KnownFPClass PartiallyPoison =2202 computeKnownFPClass(ConstantVector::get({NegZeroF32, PoisonF32}),2203 M->getDataLayout(), fcAllFlags);2204 EXPECT_EQ(fcNegZero, PartiallyPoison.KnownFPClasses);2205 ASSERT_TRUE(PartiallyPoison.SignBit);2206 EXPECT_TRUE(*PartiallyPoison.SignBit);2207 }2208 2209 {2210 // Assume the poison element should be 1.2211 Constant *NegZeroF32 = ConstantFP::getZero(F32, true);2212 Constant *PoisonF32 = PoisonValue::get(F32);2213 2214 KnownFPClass PartiallyPoison =2215 computeKnownFPClass(ConstantVector::get({PoisonF32, NegZeroF32}),2216 M->getDataLayout(), fcAllFlags);2217 EXPECT_EQ(fcNegZero, PartiallyPoison.KnownFPClasses);2218 EXPECT_TRUE(PartiallyPoison.SignBit);2219 }2220}2221 2222TEST_F(ComputeKnownFPClassTest, fcmpImpliesClass_fabs_zero) {2223 parseAssembly("define float @test(float %x) {\n"2224 " %A = call float @llvm.fabs.f32(float %x)\n"2225 " ret float %A\n"2226 "}\n");2227 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OEQ, *F, A, fcZero)),2228 fcZero);2229 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UEQ, *F, A, fcZero)),2230 fcZero | fcNan);2231 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UNE, *F, A, fcZero)),2232 ~fcZero);2233 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ONE, *F, A, fcZero)),2234 ~fcNan & ~fcZero);2235 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ORD, *F, A, fcZero)),2236 ~fcNan);2237 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UNO, *F, A, fcZero)),2238 fcNan);2239 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OGT, *F, A, fcZero)),2240 fcSubnormal | fcNormal | fcInf);2241 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UGT, *F, A, fcZero)),2242 fcSubnormal | fcNormal | fcInf | fcNan);2243 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OGE, *F, A, fcZero)),2244 ~fcNan);2245 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UGE, *F, A, fcZero)),2246 fcAllFlags);2247 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OLT, *F, A, fcZero)),2248 fcNone);2249 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ULT, *F, A, fcZero)),2250 fcNan);2251 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OLE, *F, A, fcZero)),2252 fcZero);2253 EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ULE, *F, A, fcZero)),2254 fcZero | fcNan);2255}2256 2257TEST_F(ValueTrackingTest, isNonZeroRecurrence) {2258 parseAssembly(R"(2259 define i1 @test(i8 %n, i8 %r) {2260 entry:2261 br label %loop2262 loop:2263 %p = phi i8 [ -1, %entry ], [ %next, %loop ]2264 %next = add nsw i8 %p, -12265 %cmp1 = icmp eq i8 %p, %n2266 br i1 %cmp1, label %exit, label %loop2267 exit:2268 %A = or i8 %p, %r2269 %CxtI = icmp eq i8 %A, 02270 ret i1 %CxtI2271 }2272 )");2273 const DataLayout &DL = M->getDataLayout();2274 AssumptionCache AC(*F);2275 EXPECT_TRUE(isKnownNonZero(A, SimplifyQuery(DL, /*DT=*/nullptr, &AC, CxtI)));2276}2277 2278TEST_F(ValueTrackingTest, KnownNonZeroFromDomCond) {2279 parseAssembly(R"(2280 declare ptr @f_i8()2281 define void @test(i1 %c) {2282 %A = call ptr @f_i8()2283 %B = call ptr @f_i8()2284 %c1 = icmp ne ptr %A, null2285 %cond = and i1 %c1, %c2286 br i1 %cond, label %T, label %Q2287 T:2288 %CxtI = add i32 0, 02289 ret void2290 Q:2291 %CxtI2 = add i32 0, 02292 ret void2293 }2294 )");2295 AssumptionCache AC(*F);2296 DominatorTree DT(*F);2297 const DataLayout &DL = M->getDataLayout();2298 const SimplifyQuery SQ(DL, &DT, &AC);2299 EXPECT_EQ(isKnownNonZero(A, SQ.getWithInstruction(CxtI)), true);2300 EXPECT_EQ(isKnownNonZero(A, SQ.getWithInstruction(CxtI2)), false);2301}2302 2303TEST_F(ValueTrackingTest, KnownNonZeroFromDomCond2) {2304 parseAssembly(R"(2305 declare ptr @f_i8()2306 define void @test(i1 %c) {2307 %A = call ptr @f_i8()2308 %B = call ptr @f_i8()2309 %c1 = icmp ne ptr %A, null2310 %cond = select i1 %c, i1 %c1, i1 false2311 br i1 %cond, label %T, label %Q2312 T:2313 %CxtI = add i32 0, 02314 ret void2315 Q:2316 %CxtI2 = add i32 0, 02317 ret void2318 }2319 )");2320 AssumptionCache AC(*F);2321 DominatorTree DT(*F);2322 const DataLayout &DL = M->getDataLayout();2323 const SimplifyQuery SQ(DL, &DT, &AC);2324 EXPECT_EQ(isKnownNonZero(A, SQ.getWithInstruction(CxtI)), true);2325 EXPECT_EQ(isKnownNonZero(A, SQ.getWithInstruction(CxtI2)), false);2326}2327 2328TEST_F(ValueTrackingTest, IsImpliedConditionAnd) {2329 parseAssembly(R"(2330 define void @test(i32 %x, i32 %y) {2331 %c1 = icmp ult i32 %x, 102332 %c2 = icmp ult i32 %y, 152333 %A = and i1 %c1, %c22334 ; x < 10 /\ y < 152335 %A2 = icmp ult i32 %x, 202336 %A3 = icmp uge i32 %y, 202337 %A4 = icmp ult i32 %x, 52338 ret void2339 }2340 )");2341 const DataLayout &DL = M->getDataLayout();2342 EXPECT_EQ(isImpliedCondition(A, A2, DL), true);2343 EXPECT_EQ(isImpliedCondition(A, A3, DL), false);2344 EXPECT_EQ(isImpliedCondition(A, A4, DL), std::nullopt);2345}2346 2347TEST_F(ValueTrackingTest, IsImpliedConditionAnd2) {2348 parseAssembly(R"(2349 define void @test(i32 %x, i32 %y) {2350 %c1 = icmp ult i32 %x, 102351 %c2 = icmp ult i32 %y, 152352 %A = select i1 %c1, i1 %c2, i1 false2353 ; x < 10 /\ y < 152354 %A2 = icmp ult i32 %x, 202355 %A3 = icmp uge i32 %y, 202356 %A4 = icmp ult i32 %x, 52357 ret void2358 }2359 )");2360 const DataLayout &DL = M->getDataLayout();2361 EXPECT_EQ(isImpliedCondition(A, A2, DL), true);2362 EXPECT_EQ(isImpliedCondition(A, A3, DL), false);2363 EXPECT_EQ(isImpliedCondition(A, A4, DL), std::nullopt);2364}2365 2366TEST_F(ValueTrackingTest, IsImpliedConditionAndVec) {2367 parseAssembly(R"(2368 define void @test(<2 x i8> %x, <2 x i8> %y) {2369 %A = icmp ult <2 x i8> %x, %y2370 %A2 = icmp ule <2 x i8> %x, %y2371 ret void2372 }2373 )");2374 const DataLayout &DL = M->getDataLayout();2375 EXPECT_EQ(isImpliedCondition(A, A2, DL), true);2376}2377 2378TEST_F(ValueTrackingTest, IsImpliedConditionOr) {2379 parseAssembly(R"(2380 define void @test(i32 %x, i32 %y) {2381 %c1 = icmp ult i32 %x, 102382 %c2 = icmp ult i32 %y, 152383 %A = or i1 %c1, %c2 ; negated2384 ; x >= 10 /\ y >= 152385 %A2 = icmp ult i32 %x, 52386 %A3 = icmp uge i32 %y, 102387 %A4 = icmp ult i32 %x, 152388 ret void2389 }2390 )");2391 const DataLayout &DL = M->getDataLayout();2392 EXPECT_EQ(isImpliedCondition(A, A2, DL, false), false);2393 EXPECT_EQ(isImpliedCondition(A, A3, DL, false), true);2394 EXPECT_EQ(isImpliedCondition(A, A4, DL, false), std::nullopt);2395}2396 2397TEST_F(ValueTrackingTest, IsImpliedConditionOr2) {2398 parseAssembly(R"(2399 define void @test(i32 %x, i32 %y) {2400 %c1 = icmp ult i32 %x, 102401 %c2 = icmp ult i32 %y, 152402 %A = select i1 %c1, i1 true, i1 %c2 ; negated2403 ; x >= 10 /\ y >= 152404 %A2 = icmp ult i32 %x, 52405 %A3 = icmp uge i32 %y, 102406 %A4 = icmp ult i32 %x, 152407 ret void2408 }2409 )");2410 const DataLayout &DL = M->getDataLayout();2411 EXPECT_EQ(isImpliedCondition(A, A2, DL, false), false);2412 EXPECT_EQ(isImpliedCondition(A, A3, DL, false), true);2413 EXPECT_EQ(isImpliedCondition(A, A4, DL, false), std::nullopt);2414}2415 2416TEST_F(ComputeKnownBitsTest, KnownNonZeroShift) {2417 // %q is known nonzero without known bits.2418 // Because %q is nonzero, %A[0] is known to be zero.2419 parseAssembly(2420 "define i8 @test(i8 %p, ptr %pq) {\n"2421 " %q = load i8, ptr %pq, !range !0\n"2422 " %A = shl i8 %p, %q\n"2423 " ret i8 %A\n"2424 "}\n"2425 "!0 = !{ i8 1, i8 5 }\n");2426 expectKnownBits(/*zero*/ 1u, /*one*/ 0u);2427}2428 2429TEST_F(ComputeKnownBitsTest, ComputeKnownFshl) {2430 // fshl(....1111....0000, 00..1111........, 6)2431 // = 11....000000..112432 parseAssembly(2433 "define i16 @test(i16 %a, i16 %b) {\n"2434 " %aa = shl i16 %a, 4\n"2435 " %bb = lshr i16 %b, 2\n"2436 " %aaa = or i16 %aa, 3840\n"2437 " %bbb = or i16 %bb, 3840\n"2438 " %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 6)\n"2439 " ret i16 %A\n"2440 "}\n"2441 "declare i16 @llvm.fshl.i16(i16, i16, i16)\n");2442 expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u);2443}2444 2445TEST_F(ComputeKnownBitsTest, ComputeKnownFshr) {2446 // fshr(....1111....0000, 00..1111........, 26)2447 // = 11....000000..112448 parseAssembly(2449 "define i16 @test(i16 %a, i16 %b) {\n"2450 " %aa = shl i16 %a, 4\n"2451 " %bb = lshr i16 %b, 2\n"2452 " %aaa = or i16 %aa, 3840\n"2453 " %bbb = or i16 %bb, 3840\n"2454 " %A = call i16 @llvm.fshr.i16(i16 %aaa, i16 %bbb, i16 26)\n"2455 " ret i16 %A\n"2456 "}\n"2457 "declare i16 @llvm.fshr.i16(i16, i16, i16)\n");2458 expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u);2459}2460 2461TEST_F(ComputeKnownBitsTest, ComputeKnownFshlZero) {2462 // fshl(....1111....0000, 00..1111........, 0)2463 // = ....1111....00002464 parseAssembly(2465 "define i16 @test(i16 %a, i16 %b) {\n"2466 " %aa = shl i16 %a, 4\n"2467 " %bb = lshr i16 %b, 2\n"2468 " %aaa = or i16 %aa, 3840\n"2469 " %bbb = or i16 %bb, 3840\n"2470 " %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 0)\n"2471 " ret i16 %A\n"2472 "}\n"2473 "declare i16 @llvm.fshl.i16(i16, i16, i16)\n");2474 expectKnownBits(/*zero*/ 15u, /*one*/ 3840u);2475}2476 2477TEST_F(ComputeKnownBitsTest, ComputeKnownUAddSatLeadingOnes) {2478 // uadd.sat(1111...1, ........)2479 // = 1111....2480 parseAssembly(2481 "define i8 @test(i8 %a, i8 %b) {\n"2482 " %aa = or i8 %a, 241\n"2483 " %A = call i8 @llvm.uadd.sat.i8(i8 %aa, i8 %b)\n"2484 " ret i8 %A\n"2485 "}\n"2486 "declare i8 @llvm.uadd.sat.i8(i8, i8)\n");2487 expectKnownBits(/*zero*/ 0u, /*one*/ 240u);2488}2489 2490TEST_F(ComputeKnownBitsTest, ComputeKnownUAddSatOnesPreserved) {2491 // uadd.sat(00...011, .1...110)2492 // = .......12493 parseAssembly(2494 "define i8 @test(i8 %a, i8 %b) {\n"2495 " %aa = or i8 %a, 3\n"2496 " %aaa = and i8 %aa, 59\n"2497 " %bb = or i8 %b, 70\n"2498 " %bbb = and i8 %bb, 254\n"2499 " %A = call i8 @llvm.uadd.sat.i8(i8 %aaa, i8 %bbb)\n"2500 " ret i8 %A\n"2501 "}\n"2502 "declare i8 @llvm.uadd.sat.i8(i8, i8)\n");2503 expectKnownBits(/*zero*/ 0u, /*one*/ 1u);2504}2505 2506TEST_F(ComputeKnownBitsTest, ComputeKnownUSubSatLHSLeadingZeros) {2507 // usub.sat(0000...0, ........)2508 // = 0000....2509 parseAssembly(2510 "define i8 @test(i8 %a, i8 %b) {\n"2511 " %aa = and i8 %a, 14\n"2512 " %A = call i8 @llvm.usub.sat.i8(i8 %aa, i8 %b)\n"2513 " ret i8 %A\n"2514 "}\n"2515 "declare i8 @llvm.usub.sat.i8(i8, i8)\n");2516 expectKnownBits(/*zero*/ 240u, /*one*/ 0u);2517}2518 2519TEST_F(ComputeKnownBitsTest, ComputeKnownUSubSatRHSLeadingOnes) {2520 // usub.sat(........, 1111...1)2521 // = 0000....2522 parseAssembly(2523 "define i8 @test(i8 %a, i8 %b) {\n"2524 " %bb = or i8 %a, 241\n"2525 " %A = call i8 @llvm.usub.sat.i8(i8 %a, i8 %bb)\n"2526 " ret i8 %A\n"2527 "}\n"2528 "declare i8 @llvm.usub.sat.i8(i8, i8)\n");2529 expectKnownBits(/*zero*/ 240u, /*one*/ 0u);2530}2531 2532TEST_F(ComputeKnownBitsTest, ComputeKnownUSubSatZerosPreserved) {2533 // usub.sat(11...011, .1...110)2534 // = ......0.2535 parseAssembly(2536 "define i8 @test(i8 %a, i8 %b) {\n"2537 " %aa = or i8 %a, 195\n"2538 " %aaa = and i8 %aa, 251\n"2539 " %bb = or i8 %b, 70\n"2540 " %bbb = and i8 %bb, 254\n"2541 " %A = call i8 @llvm.usub.sat.i8(i8 %aaa, i8 %bbb)\n"2542 " ret i8 %A\n"2543 "}\n"2544 "declare i8 @llvm.usub.sat.i8(i8, i8)\n");2545 expectKnownBits(/*zero*/ 2u, /*one*/ 0u);2546}2547 2548TEST_F(ComputeKnownBitsTest, ComputeKnownBitsPtrToIntTrunc) {2549 // ptrtoint truncates the pointer type. Make sure we don't crash.2550 parseAssembly(2551 "define void @test(ptr %p) {\n"2552 " %A = load ptr, ptr %p\n"2553 " %i = ptrtoint ptr %A to i32\n"2554 " %m = and i32 %i, 31\n"2555 " %c = icmp eq i32 %m, 0\n"2556 " call void @llvm.assume(i1 %c)\n"2557 " ret void\n"2558 "}\n"2559 "declare void @llvm.assume(i1)\n");2560 AssumptionCache AC(*F);2561 KnownBits Known =2562 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2563 EXPECT_TRUE(Known.isUnknown());2564}2565 2566TEST_F(ComputeKnownBitsTest, ComputeKnownBitsPtrToIntZext) {2567 // ptrtoint zero extends the pointer type. Make sure we don't crash.2568 parseAssembly(2569 "define void @test(ptr %p) {\n"2570 " %A = load ptr, ptr %p\n"2571 " %i = ptrtoint ptr %A to i128\n"2572 " %m = and i128 %i, 31\n"2573 " %c = icmp eq i128 %m, 0\n"2574 " call void @llvm.assume(i1 %c)\n"2575 " ret void\n"2576 "}\n"2577 "declare void @llvm.assume(i1)\n");2578 AssumptionCache AC(*F);2579 KnownBits Known =2580 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2581 EXPECT_TRUE(Known.isUnknown());2582}2583 2584TEST_F(ComputeKnownBitsTest, ComputeKnownBitsFreeze) {2585 parseAssembly("define void @test() {\n"2586 " %m = call i32 @any_num()\n"2587 " %A = freeze i32 %m\n"2588 " %n = and i32 %m, 31\n"2589 " %c = icmp eq i32 %n, 0\n"2590 " call void @llvm.assume(i1 %c)\n"2591 " ret void\n"2592 "}\n"2593 "declare void @llvm.assume(i1)\n"2594 "declare i32 @any_num()\n");2595 AssumptionCache AC(*F);2596 KnownBits Known =2597 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2598 EXPECT_EQ(Known.Zero.getZExtValue(), 31u);2599 EXPECT_EQ(Known.One.getZExtValue(), 0u);2600}2601 2602TEST_F(ComputeKnownBitsTest, ComputeKnownBitsReturnedRangeConflict) {2603 parseAssembly(2604 "declare i16 @foo(i16 returned)\n"2605 "\n"2606 "define i16 @test() {\n"2607 " %A = call i16 @foo(i16 4095), !range !{i16 32, i16 33}\n"2608 " ret i16 %A\n"2609 "}\n");2610 // The call returns 32 according to range metadata, but 4095 according to the2611 // returned arg operand. Given the conflicting information we expect that the2612 // known bits information simply is cleared.2613 expectKnownBits(/*zero*/ 0u, /*one*/ 0u);2614}2615 2616TEST_F(ComputeKnownBitsTest, ComputeKnownBitsAddWithRange) {2617 parseAssembly("define void @test(ptr %p) {\n"2618 " %A = load i64, ptr %p, !range !{i64 64, i64 65536}\n"2619 " %APlus512 = add i64 %A, 512\n"2620 " %c = icmp ugt i64 %APlus512, 523\n"2621 " call void @llvm.assume(i1 %c)\n"2622 " ret void\n"2623 "}\n"2624 "declare void @llvm.assume(i1)\n");2625 AssumptionCache AC(*F);2626 KnownBits Known =2627 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2628 EXPECT_EQ(Known.Zero.getZExtValue(), ~(65536llu - 1));2629 EXPECT_EQ(Known.One.getZExtValue(), 0u);2630 Instruction &APlus512 = findInstructionByName(F, "APlus512");2631 Known = computeKnownBits(&APlus512, M->getDataLayout(), &AC,2632 F->front().getTerminator());2633 // We know of one less zero because 512 may have produced a 1 that2634 // got carried all the way to the first trailing zero.2635 EXPECT_EQ(Known.Zero.getZExtValue(), (~(65536llu - 1)) << 1);2636 EXPECT_EQ(Known.One.getZExtValue(), 0u);2637 // The known range is not precise given computeKnownBits works2638 // with the masks of zeros and ones, not the ranges.2639 EXPECT_EQ(Known.getMinValue(), 0u);2640 EXPECT_EQ(Known.getMaxValue(), 131071);2641}2642 2643TEST_F(ComputeKnownBitsTest, ComputeKnownBitsUnknownVScale) {2644 Module M("", Context);2645 IRBuilder<> Builder(Context);2646 Function *TheFn = Intrinsic::getOrInsertDeclaration(&M, Intrinsic::vscale,2647 {Builder.getInt32Ty()});2648 CallInst *CI = Builder.CreateCall(TheFn, {}, {}, "");2649 2650 KnownBits Known = computeKnownBits(CI, M.getDataLayout());2651 // There is no parent function so we cannot look up the vscale_range2652 // attribute to determine the number of bits.2653 EXPECT_EQ(Known.One.getZExtValue(), 0u);2654 EXPECT_EQ(Known.Zero.getZExtValue(), 0u);2655 2656 BasicBlock *BB = BasicBlock::Create(Context);2657 CI->insertInto(BB, BB->end());2658 Known = computeKnownBits(CI, M.getDataLayout());2659 // There is no parent function so we cannot look up the vscale_range2660 // attribute to determine the number of bits.2661 EXPECT_EQ(Known.One.getZExtValue(), 0u);2662 EXPECT_EQ(Known.Zero.getZExtValue(), 0u);2663 2664 CI->removeFromParent();2665 delete CI;2666 delete BB;2667}2668 2669// 512 + [32, 64) doesn't produce overlapping bits.2670// Make sure we get all the individual bits properly.2671TEST_F(ComputeKnownBitsTest, ComputeKnownBitsAddWithRangeNoOverlap) {2672 parseAssembly("define void @test(ptr %p) {\n"2673 " %A = load i64, ptr %p, !range !{i64 32, i64 64}\n"2674 " %APlus512 = add i64 %A, 512\n"2675 " %c = icmp ugt i64 %APlus512, 523\n"2676 " call void @llvm.assume(i1 %c)\n"2677 " ret void\n"2678 "}\n"2679 "declare void @llvm.assume(i1)\n");2680 AssumptionCache AC(*F);2681 KnownBits Known =2682 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2683 EXPECT_EQ(Known.Zero.getZExtValue(), ~(64llu - 1));2684 EXPECT_EQ(Known.One.getZExtValue(), 32u);2685 Instruction &APlus512 = findInstructionByName(F, "APlus512");2686 Known = computeKnownBits(&APlus512, M->getDataLayout(), &AC,2687 F->front().getTerminator());2688 EXPECT_EQ(Known.Zero.getZExtValue(), ~512llu & ~(64llu - 1));2689 EXPECT_EQ(Known.One.getZExtValue(), 512u | 32u);2690 // The known range is not precise given computeKnownBits works2691 // with the masks of zeros and ones, not the ranges.2692 EXPECT_EQ(Known.getMinValue(), 544);2693 EXPECT_EQ(Known.getMaxValue(), 575);2694}2695 2696TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPWithRange) {2697 parseAssembly(2698 "define void @test(ptr %p) {\n"2699 " %A = load i64, ptr %p, !range !{i64 64, i64 65536}\n"2700 " %APtr = inttoptr i64 %A to ptr"2701 " %APtrPlus512 = getelementptr float, ptr %APtr, i32 128\n"2702 " %c = icmp ugt ptr %APtrPlus512, inttoptr (i32 523 to ptr)\n"2703 " call void @llvm.assume(i1 %c)\n"2704 " ret void\n"2705 "}\n"2706 "declare void @llvm.assume(i1)\n");2707 AssumptionCache AC(*F);2708 KnownBits Known =2709 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2710 EXPECT_EQ(Known.Zero.getZExtValue(), ~(65536llu - 1));2711 EXPECT_EQ(Known.One.getZExtValue(), 0u);2712 Instruction &APtrPlus512 = findInstructionByName(F, "APtrPlus512");2713 Known = computeKnownBits(&APtrPlus512, M->getDataLayout(), &AC,2714 F->front().getTerminator());2715 // We know of one less zero because 512 may have produced a 1 that2716 // got carried all the way to the first trailing zero.2717 EXPECT_EQ(Known.Zero.getZExtValue(), ~(65536llu - 1) << 1);2718 EXPECT_EQ(Known.One.getZExtValue(), 0u);2719 // The known range is not precise given computeKnownBits works2720 // with the masks of zeros and ones, not the ranges.2721 EXPECT_EQ(Known.getMinValue(), 0u);2722 EXPECT_EQ(Known.getMaxValue(), 131071);2723}2724 2725// 4*128 + [32, 64) doesn't produce overlapping bits.2726// Make sure we get all the individual bits properly.2727// This test is useful to check that we account for the scaling factor2728// in the gep. Indeed, gep float, [32,64), 128 is not 128 + [32,64).2729TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPWithRangeNoOverlap) {2730 parseAssembly(2731 "define void @test(ptr %p) {\n"2732 " %A = load i64, ptr %p, !range !{i64 32, i64 64}\n"2733 " %APtr = inttoptr i64 %A to ptr"2734 " %APtrPlus512 = getelementptr float, ptr %APtr, i32 128\n"2735 " %c = icmp ugt ptr %APtrPlus512, inttoptr (i32 523 to ptr)\n"2736 " call void @llvm.assume(i1 %c)\n"2737 " ret void\n"2738 "}\n"2739 "declare void @llvm.assume(i1)\n");2740 AssumptionCache AC(*F);2741 KnownBits Known =2742 computeKnownBits(A, M->getDataLayout(), &AC, F->front().getTerminator());2743 EXPECT_EQ(Known.Zero.getZExtValue(), ~(64llu - 1));2744 EXPECT_EQ(Known.One.getZExtValue(), 32u);2745 Instruction &APtrPlus512 = findInstructionByName(F, "APtrPlus512");2746 Known = computeKnownBits(&APtrPlus512, M->getDataLayout(), &AC,2747 F->front().getTerminator());2748 EXPECT_EQ(Known.Zero.getZExtValue(), ~512llu & ~(64llu - 1));2749 EXPECT_EQ(Known.One.getZExtValue(), 512u | 32u);2750 // The known range is not precise given computeKnownBits works2751 // with the masks of zeros and ones, not the ranges.2752 EXPECT_EQ(Known.getMinValue(), 544);2753 EXPECT_EQ(Known.getMaxValue(), 575);2754}2755 2756TEST_F(ComputeKnownBitsTest, ComputeKnownBitsAbsoluteSymbol) {2757 auto M = parseModule(R"(2758 @absolute_0_255 = external global [128 x i32], align 1, !absolute_symbol !02759 @absolute_0_256 = external global [128 x i32], align 1, !absolute_symbol !12760 @absolute_256_512 = external global [128 x i32], align 1, !absolute_symbol !22761 @absolute_0_neg1 = external global [128 x i32], align 1, !absolute_symbol !32762 @absolute_neg32_32 = external global [128 x i32], align 1, !absolute_symbol !42763 @absolute_neg32_33 = external global [128 x i32], align 1, !absolute_symbol !52764 @absolute_neg64_neg32 = external global [128 x i32], align 1, !absolute_symbol !62765 @absolute_0_256_align8 = external global [128 x i32], align 8, !absolute_symbol !12766 2767 !0 = !{i64 0, i64 255}2768 !1 = !{i64 0, i64 256}2769 !2 = !{i64 256, i64 512}2770 !3 = !{i64 0, i64 -1}2771 !4 = !{i64 -32, i64 32}2772 !5 = !{i64 -32, i64 33}2773 !6 = !{i64 -64, i64 -32}2774 )");2775 2776 GlobalValue *Absolute_0_255 = M->getNamedValue("absolute_0_255");2777 GlobalValue *Absolute_0_256 = M->getNamedValue("absolute_0_256");2778 GlobalValue *Absolute_256_512 = M->getNamedValue("absolute_256_512");2779 GlobalValue *Absolute_0_Neg1 = M->getNamedValue("absolute_0_neg1");2780 GlobalValue *Absolute_Neg32_32 = M->getNamedValue("absolute_neg32_32");2781 GlobalValue *Absolute_Neg32_33 = M->getNamedValue("absolute_neg32_33");2782 GlobalValue *Absolute_Neg64_Neg32 = M->getNamedValue("absolute_neg64_neg32");2783 GlobalValue *Absolute_0_256_Align8 =2784 M->getNamedValue("absolute_0_256_align8");2785 2786 KnownBits Known_0_255 = computeKnownBits(Absolute_0_255, M->getDataLayout());2787 EXPECT_EQ(64u - 8u, Known_0_255.countMinLeadingZeros());2788 EXPECT_EQ(0u, Known_0_255.countMinTrailingZeros());2789 EXPECT_EQ(0u, Known_0_255.countMinLeadingOnes());2790 EXPECT_EQ(0u, Known_0_255.countMinTrailingOnes());2791 2792 KnownBits Known_0_256 = computeKnownBits(Absolute_0_256, M->getDataLayout());2793 EXPECT_EQ(64u - 8u, Known_0_256.countMinLeadingZeros());2794 EXPECT_EQ(0u, Known_0_256.countMinTrailingZeros());2795 EXPECT_EQ(0u, Known_0_256.countMinLeadingOnes());2796 EXPECT_EQ(0u, Known_0_256.countMinTrailingOnes());2797 2798 KnownBits Known_256_512 =2799 computeKnownBits(Absolute_256_512, M->getDataLayout());2800 EXPECT_EQ(64u - 8u, Known_0_255.countMinLeadingZeros());2801 EXPECT_EQ(0u, Known_0_255.countMinTrailingZeros());2802 EXPECT_EQ(0u, Known_0_255.countMinLeadingOnes());2803 EXPECT_EQ(0u, Known_0_255.countMinTrailingOnes());2804 2805 KnownBits Known_0_Neg1 =2806 computeKnownBits(Absolute_0_Neg1, M->getDataLayout());2807 EXPECT_EQ(0u, Known_0_Neg1.countMinLeadingZeros());2808 EXPECT_EQ(0u, Known_0_Neg1.countMinTrailingZeros());2809 EXPECT_EQ(0u, Known_0_Neg1.countMinLeadingOnes());2810 EXPECT_EQ(0u, Known_0_Neg1.countMinTrailingOnes());2811 2812 KnownBits Known_Neg32_32 =2813 computeKnownBits(Absolute_Neg32_32, M->getDataLayout());2814 EXPECT_EQ(0u, Known_Neg32_32.countMinLeadingZeros());2815 EXPECT_EQ(0u, Known_Neg32_32.countMinTrailingZeros());2816 EXPECT_EQ(0u, Known_Neg32_32.countMinLeadingOnes());2817 EXPECT_EQ(0u, Known_Neg32_32.countMinTrailingOnes());2818 EXPECT_EQ(1u, Known_Neg32_32.countMinSignBits());2819 2820 KnownBits Known_Neg32_33 =2821 computeKnownBits(Absolute_Neg32_33, M->getDataLayout());2822 EXPECT_EQ(0u, Known_Neg32_33.countMinLeadingZeros());2823 EXPECT_EQ(0u, Known_Neg32_33.countMinTrailingZeros());2824 EXPECT_EQ(0u, Known_Neg32_33.countMinLeadingOnes());2825 EXPECT_EQ(0u, Known_Neg32_33.countMinTrailingOnes());2826 EXPECT_EQ(1u, Known_Neg32_33.countMinSignBits());2827 2828 KnownBits Known_Neg32_Neg32 =2829 computeKnownBits(Absolute_Neg64_Neg32, M->getDataLayout());2830 EXPECT_EQ(0u, Known_Neg32_Neg32.countMinLeadingZeros());2831 EXPECT_EQ(0u, Known_Neg32_Neg32.countMinTrailingZeros());2832 EXPECT_EQ(58u, Known_Neg32_Neg32.countMinLeadingOnes());2833 EXPECT_EQ(0u, Known_Neg32_Neg32.countMinTrailingOnes());2834 EXPECT_EQ(58u, Known_Neg32_Neg32.countMinSignBits());2835 2836 KnownBits Known_0_256_Align8 =2837 computeKnownBits(Absolute_0_256_Align8, M->getDataLayout());2838 EXPECT_EQ(64u - 8u, Known_0_256_Align8.countMinLeadingZeros());2839 EXPECT_EQ(3u, Known_0_256_Align8.countMinTrailingZeros());2840 EXPECT_EQ(0u, Known_0_256_Align8.countMinLeadingOnes());2841 EXPECT_EQ(0u, Known_0_256_Align8.countMinTrailingOnes());2842}2843 2844TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPExtendBeforeMul) {2845 // The index should be extended before multiplying with the scale.2846 parseAssembly(R"(2847 target datalayout = "p:16:16:16"2848 2849 define void @test(i16 %arg) {2850 %and = and i16 %arg, u0x80002851 %base = inttoptr i16 %and to ptr2852 %A = getelementptr i32, ptr %base, i8 802853 ret void2854 }2855 )");2856 KnownBits Known = computeKnownBits(A, M->getDataLayout());2857 EXPECT_EQ(~320 & 0x7fff, Known.Zero);2858 EXPECT_EQ(320, Known.One);2859}2860 2861TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPOnlyIndexBits) {2862 // GEP should only affect the index width.2863 parseAssembly(R"(2864 target datalayout = "p:16:16:16:8"2865 2866 define void @test(i16 %arg) {2867 %and = and i16 %arg, u0x80002868 %or = or i16 %and, u0x00ff2869 %base = inttoptr i16 %or to ptr2870 %A = getelementptr i8, ptr %base, i8 12871 ret void2872 }2873 )");2874 KnownBits Known = computeKnownBits(A, M->getDataLayout());2875 EXPECT_EQ(0x7fff, Known.Zero);2876 EXPECT_EQ(0, Known.One);2877}2878 2879TEST_F(ValueTrackingTest, HaveNoCommonBitsSet) {2880 {2881 // Check for an inverted mask: (X & ~M) op (Y & M).2882 auto M = parseModule(R"(2883 define i32 @test(i32 %X, i32 %Y, i32 noundef %M) {2884 %1 = xor i32 %M, -12885 %LHS = and i32 %1, %X2886 %RHS = and i32 %Y, %M2887 %Ret = add i32 %LHS, %RHS2888 ret i32 %Ret2889 })");2890 2891 auto *F = M->getFunction("test");2892 auto *LHS = findInstructionByNameOrNull(F, "LHS");2893 auto *RHS = findInstructionByNameOrNull(F, "RHS");2894 2895 const DataLayout &DL = M->getDataLayout();2896 EXPECT_TRUE(haveNoCommonBitsSet(LHS, RHS, DL));2897 EXPECT_TRUE(haveNoCommonBitsSet(RHS, LHS, DL));2898 }2899 {2900 // Check for (A & B) and ~(A | B)2901 auto M = parseModule(R"(2902 define void @test(i32 noundef %A, i32 noundef %B) {2903 %LHS = and i32 %A, %B2904 %or = or i32 %A, %B2905 %RHS = xor i32 %or, -12906 2907 %LHS2 = and i32 %B, %A2908 %or2 = or i32 %A, %B2909 %RHS2 = xor i32 %or2, -12910 2911 ret void2912 })");2913 2914 auto *F = M->getFunction("test");2915 const DataLayout &DL = M->getDataLayout();2916 2917 auto *LHS = findInstructionByNameOrNull(F, "LHS");2918 auto *RHS = findInstructionByNameOrNull(F, "RHS");2919 EXPECT_TRUE(haveNoCommonBitsSet(LHS, RHS, DL));2920 EXPECT_TRUE(haveNoCommonBitsSet(RHS, LHS, DL));2921 2922 auto *LHS2 = findInstructionByNameOrNull(F, "LHS2");2923 auto *RHS2 = findInstructionByNameOrNull(F, "RHS2");2924 EXPECT_TRUE(haveNoCommonBitsSet(LHS2, RHS2, DL));2925 EXPECT_TRUE(haveNoCommonBitsSet(RHS2, LHS2, DL));2926 }2927 {2928 // Check for (A & B) and ~(A | B) in vector version2929 auto M = parseModule(R"(2930 define void @test(<2 x i32> noundef %A, <2 x i32> noundef %B) {2931 %LHS = and <2 x i32> %A, %B2932 %or = or <2 x i32> %A, %B2933 %RHS = xor <2 x i32> %or, <i32 -1, i32 -1>2934 2935 %LHS2 = and <2 x i32> %B, %A2936 %or2 = or <2 x i32> %A, %B2937 %RHS2 = xor <2 x i32> %or2, <i32 -1, i32 -1>2938 2939 ret void2940 })");2941 2942 auto *F = M->getFunction("test");2943 const DataLayout &DL = M->getDataLayout();2944 2945 auto *LHS = findInstructionByNameOrNull(F, "LHS");2946 auto *RHS = findInstructionByNameOrNull(F, "RHS");2947 EXPECT_TRUE(haveNoCommonBitsSet(LHS, RHS, DL));2948 EXPECT_TRUE(haveNoCommonBitsSet(RHS, LHS, DL));2949 2950 auto *LHS2 = findInstructionByNameOrNull(F, "LHS2");2951 auto *RHS2 = findInstructionByNameOrNull(F, "RHS2");2952 EXPECT_TRUE(haveNoCommonBitsSet(LHS2, RHS2, DL));2953 EXPECT_TRUE(haveNoCommonBitsSet(RHS2, LHS2, DL));2954 }2955}2956 2957class IsBytewiseValueTest : public ValueTrackingTest,2958 public ::testing::WithParamInterface<2959 std::pair<const char *, const char *>> {2960protected:2961};2962 2963const std::pair<const char *, const char *> IsBytewiseValueTests[] = {2964 {2965 "i8 0",2966 "ptr null",2967 },2968 {2969 "i8 undef",2970 "ptr undef",2971 },2972 {2973 "i8 0",2974 "i8 zeroinitializer",2975 },2976 {2977 "i8 0",2978 "i8 0",2979 },2980 {2981 "i8 -86",2982 "i8 -86",2983 },2984 {2985 "i8 -1",2986 "i8 -1",2987 },2988 {2989 "i8 undef",2990 "i16 undef",2991 },2992 {2993 "i8 0",2994 "i16 0",2995 },2996 {2997 "",2998 "i16 7",2999 },3000 {3001 "i8 -86",3002 "i16 -21846",3003 },3004 {3005 "i8 -1",3006 "i16 -1",3007 },3008 {3009 "i8 0",3010 "i48 0",3011 },3012 {3013 "i8 -1",3014 "i48 -1",3015 },3016 {3017 "i8 0",3018 "i49 0",3019 },3020 {3021 "",3022 "i49 -1",3023 },3024 {3025 "i8 0",3026 "half 0xH0000",3027 },3028 {3029 "i8 -85",3030 "half 0xHABAB",3031 },3032 {3033 "i8 0",3034 "float 0.0",3035 },3036 {3037 "i8 -1",3038 "float 0xFFFFFFFFE0000000",3039 },3040 {3041 "i8 0",3042 "double 0.0",3043 },3044 {3045 "i8 -15",3046 "double 0xF1F1F1F1F1F1F1F1",3047 },3048 {3049 "i8 0",3050 "ptr inttoptr (i64 0 to ptr)",3051 },3052 {3053 "i8 -1",3054 "ptr inttoptr (i64 -1 to ptr)",3055 },3056 {3057 "i8 -86",3058 "ptr inttoptr (i64 -6148914691236517206 to ptr)",3059 },3060 {3061 "",3062 "ptr inttoptr (i48 -1 to ptr)",3063 },3064 {3065 "i8 -1",3066 "ptr inttoptr (i96 -1 to ptr)",3067 },3068 {3069 "i8 poison",3070 "[0 x i8] zeroinitializer",3071 },3072 {3073 "i8 undef",3074 "[0 x i8] undef",3075 },3076 {3077 "i8 poison",3078 "[5 x [0 x i8]] zeroinitializer",3079 },3080 {3081 "i8 undef",3082 "[5 x [0 x i8]] undef",3083 },3084 {3085 "i8 0",3086 "[6 x i8] zeroinitializer",3087 },3088 {3089 "i8 undef",3090 "[6 x i8] undef",3091 },3092 {3093 "i8 1",3094 "[5 x i8] [i8 1, i8 1, i8 1, i8 1, i8 1]",3095 },3096 {3097 "",3098 "[5 x i64] [i64 1, i64 1, i64 1, i64 1, i64 1]",3099 },3100 {3101 "i8 -1",3102 "[5 x i64] [i64 -1, i64 -1, i64 -1, i64 -1, i64 -1]",3103 },3104 {3105 "",3106 "[4 x i8] [i8 1, i8 2, i8 1, i8 1]",3107 },3108 {3109 "i8 1",3110 "[4 x i8] [i8 1, i8 undef, i8 1, i8 1]",3111 },3112 {3113 "i8 0",3114 "<6 x i8> zeroinitializer",3115 },3116 {3117 "i8 undef",3118 "<6 x i8> undef",3119 },3120 {3121 "i8 1",3122 "<5 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1>",3123 },3124 {3125 "",3126 "<5 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1>",3127 },3128 {3129 "i8 -1",3130 "<5 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>",3131 },3132 {3133 "",3134 "<4 x i8> <i8 1, i8 1, i8 2, i8 1>",3135 },3136 {3137 "i8 5",3138 "<2 x i8> < i8 5, i8 undef >",3139 },3140 {3141 "i8 0",3142 "[2 x [2 x i16]] zeroinitializer",3143 },3144 {3145 "i8 undef",3146 "[2 x [2 x i16]] undef",3147 },3148 {3149 "i8 -86",3150 "[2 x [2 x i16]] [[2 x i16] [i16 -21846, i16 -21846], "3151 "[2 x i16] [i16 -21846, i16 -21846]]",3152 },3153 {3154 "",3155 "[2 x [2 x i16]] [[2 x i16] [i16 -21846, i16 -21846], "3156 "[2 x i16] [i16 -21836, i16 -21846]]",3157 },3158 {3159 "i8 poison",3160 "{ } zeroinitializer",3161 },3162 {3163 "i8 undef",3164 "{ } undef",3165 },3166 {3167 "i8 poison",3168 "{ {}, {} } zeroinitializer",3169 },3170 {3171 "i8 undef",3172 "{ {}, {} } undef",3173 },3174 {3175 "i8 0",3176 "{i8, i64, ptr} zeroinitializer",3177 },3178 {3179 "i8 undef",3180 "{i8, i64, ptr} undef",3181 },3182 {3183 "i8 -86",3184 "{i8, i64, ptr} {i8 -86, i64 -6148914691236517206, ptr undef}",3185 },3186 {3187 "",3188 "{i8, i64, ptr} {i8 86, i64 -6148914691236517206, ptr undef}",3189 },3190};3191 3192INSTANTIATE_TEST_SUITE_P(IsBytewiseValueParamTests, IsBytewiseValueTest,3193 ::testing::ValuesIn(IsBytewiseValueTests));3194 3195TEST_P(IsBytewiseValueTest, IsBytewiseValue) {3196 auto M = parseModule(std::string("@test = global ") + GetParam().second);3197 GlobalVariable *GV = dyn_cast<GlobalVariable>(M->getNamedValue("test"));3198 Value *Actual = isBytewiseValue(GV->getInitializer(), M->getDataLayout());3199 std::string Buff;3200 raw_string_ostream S(Buff);3201 if (Actual)3202 S << *Actual;3203 EXPECT_EQ(GetParam().first, Buff);3204}3205 3206TEST_F(ValueTrackingTest, ComputeConstantRange) {3207 {3208 // Assumptions:3209 // * stride >= 53210 // * stride < 103211 //3212 // stride = [5, 10)3213 auto M = parseModule(R"(3214 declare void @llvm.assume(i1)3215 3216 define i32 @test(i32 %stride) {3217 %gt = icmp uge i32 %stride, 53218 call void @llvm.assume(i1 %gt)3219 %lt = icmp ult i32 %stride, 103220 call void @llvm.assume(i1 %lt)3221 %stride.plus.one = add nsw nuw i32 %stride, 13222 ret i32 %stride.plus.one3223 })");3224 Function *F = M->getFunction("test");3225 3226 AssumptionCache AC(*F);3227 Value *Stride = &*F->arg_begin();3228 ConstantRange CR1 = computeConstantRange(Stride, false, true, &AC, nullptr);3229 EXPECT_TRUE(CR1.isFullSet());3230 3231 Instruction *I = &findInstructionByName(F, "stride.plus.one");3232 ConstantRange CR2 = computeConstantRange(Stride, false, true, &AC, I);3233 EXPECT_EQ(5, CR2.getLower());3234 EXPECT_EQ(10, CR2.getUpper());3235 }3236 3237 {3238 // Assumptions:3239 // * stride >= 53240 // * stride < 2003241 // * stride == 993242 //3243 // stride = [99, 100)3244 auto M = parseModule(R"(3245 declare void @llvm.assume(i1)3246 3247 define i32 @test(i32 %stride) {3248 %gt = icmp uge i32 %stride, 53249 call void @llvm.assume(i1 %gt)3250 %lt = icmp ult i32 %stride, 2003251 call void @llvm.assume(i1 %lt)3252 %eq = icmp eq i32 %stride, 993253 call void @llvm.assume(i1 %eq)3254 %stride.plus.one = add nsw nuw i32 %stride, 13255 ret i32 %stride.plus.one3256 })");3257 Function *F = M->getFunction("test");3258 3259 AssumptionCache AC(*F);3260 Value *Stride = &*F->arg_begin();3261 Instruction *I = &findInstructionByName(F, "stride.plus.one");3262 ConstantRange CR = computeConstantRange(Stride, false, true, &AC, I);3263 EXPECT_EQ(99, *CR.getSingleElement());3264 }3265 3266 {3267 // Assumptions:3268 // * stride >= 53269 // * stride >= 503270 // * stride < 1003271 // * stride < 2003272 //3273 // stride = [50, 100)3274 auto M = parseModule(R"(3275 declare void @llvm.assume(i1)3276 3277 define i32 @test(i32 %stride, i1 %cond) {3278 %gt = icmp uge i32 %stride, 53279 call void @llvm.assume(i1 %gt)3280 %gt.2 = icmp uge i32 %stride, 503281 call void @llvm.assume(i1 %gt.2)3282 br i1 %cond, label %bb1, label %bb23283 3284 bb1:3285 %lt = icmp ult i32 %stride, 2003286 call void @llvm.assume(i1 %lt)3287 %lt.2 = icmp ult i32 %stride, 1003288 call void @llvm.assume(i1 %lt.2)3289 %stride.plus.one = add nsw nuw i32 %stride, 13290 ret i32 %stride.plus.one3291 3292 bb2:3293 ret i32 03294 })");3295 Function *F = M->getFunction("test");3296 3297 AssumptionCache AC(*F);3298 Value *Stride = &*F->arg_begin();3299 Instruction *GT2 = &findInstructionByName(F, "gt.2");3300 ConstantRange CR = computeConstantRange(Stride, false, true, &AC, GT2);3301 EXPECT_EQ(5, CR.getLower());3302 EXPECT_EQ(0, CR.getUpper());3303 3304 Instruction *I = &findInstructionByName(F, "stride.plus.one");3305 ConstantRange CR2 = computeConstantRange(Stride, false, true, &AC, I);3306 EXPECT_EQ(50, CR2.getLower());3307 EXPECT_EQ(100, CR2.getUpper());3308 }3309 3310 {3311 // Assumptions:3312 // * stride > 53313 // * stride < 53314 //3315 // stride = empty range, as the assumptions contradict each other.3316 auto M = parseModule(R"(3317 declare void @llvm.assume(i1)3318 3319 define i32 @test(i32 %stride, i1 %cond) {3320 %gt = icmp ugt i32 %stride, 53321 call void @llvm.assume(i1 %gt)3322 %lt = icmp ult i32 %stride, 53323 call void @llvm.assume(i1 %lt)3324 %stride.plus.one = add nsw nuw i32 %stride, 13325 ret i32 %stride.plus.one3326 })");3327 Function *F = M->getFunction("test");3328 3329 AssumptionCache AC(*F);3330 Value *Stride = &*F->arg_begin();3331 3332 Instruction *I = &findInstructionByName(F, "stride.plus.one");3333 ConstantRange CR = computeConstantRange(Stride, false, true, &AC, I);3334 EXPECT_TRUE(CR.isEmptySet());3335 }3336 3337 {3338 // Assumptions:3339 // * x.1 >= 53340 // * x.2 < x.13341 //3342 // stride = [0, -1)3343 auto M = parseModule(R"(3344 declare void @llvm.assume(i1)3345 3346 define i32 @test(i32 %x.1, i32 %x.2) {3347 %gt = icmp uge i32 %x.1, 53348 call void @llvm.assume(i1 %gt)3349 %lt = icmp ult i32 %x.2, %x.13350 call void @llvm.assume(i1 %lt)3351 %stride.plus.one = add nsw nuw i32 %x.1, 13352 ret i32 %stride.plus.one3353 })");3354 Function *F = M->getFunction("test");3355 3356 AssumptionCache AC(*F);3357 Value *X1 = &*(F->arg_begin());3358 Value *X2 = &*std::next(F->arg_begin());3359 3360 Instruction *I = &findInstructionByName(F, "stride.plus.one");3361 ConstantRange CR1 = computeConstantRange(X1, false, true, &AC, I);3362 ConstantRange CR2 = computeConstantRange(X2, false, true, &AC, I);3363 3364 EXPECT_EQ(5, CR1.getLower());3365 EXPECT_EQ(0, CR1.getUpper());3366 3367 EXPECT_EQ(0, CR2.getLower());3368 EXPECT_EQ(0xffffffff, CR2.getUpper());3369 3370 // Check the depth cutoff results in a conservative result (full set) by3371 // passing Depth == MaxDepth == 6.3372 ConstantRange CR3 = computeConstantRange(X2, false, true, &AC, I, nullptr, 6);3373 EXPECT_TRUE(CR3.isFullSet());3374 }3375 {3376 // Assumptions:3377 // * x.2 <= x.13378 auto M = parseModule(R"(3379 declare void @llvm.assume(i1)3380 3381 define i32 @test(i32 %x.1, i32 %x.2) {3382 %lt = icmp ule i32 %x.2, %x.13383 call void @llvm.assume(i1 %lt)3384 %stride.plus.one = add nsw nuw i32 %x.1, 13385 ret i32 %stride.plus.one3386 })");3387 Function *F = M->getFunction("test");3388 3389 AssumptionCache AC(*F);3390 Value *X2 = &*std::next(F->arg_begin());3391 3392 Instruction *I = &findInstructionByName(F, "stride.plus.one");3393 ConstantRange CR1 = computeConstantRange(X2, false, true, &AC, I);3394 // If we don't know the value of x.2, we don't know the value of x.1.3395 EXPECT_TRUE(CR1.isFullSet());3396 }3397}3398 3399struct FindAllocaForValueTestParams {3400 const char *IR;3401 bool AnyOffsetResult;3402 bool ZeroOffsetResult;3403};3404 3405class FindAllocaForValueTest3406 : public ValueTrackingTest,3407 public ::testing::WithParamInterface<FindAllocaForValueTestParams> {3408protected:3409};3410 3411const FindAllocaForValueTestParams FindAllocaForValueTests[] = {3412 {R"(3413 define void @test() {3414 %a = alloca i643415 %r = bitcast ptr %a to ptr3416 ret void3417 })",3418 true, true},3419 3420 {R"(3421 define void @test() {3422 %a = alloca i323423 %r = getelementptr i32, ptr %a, i32 13424 ret void3425 })",3426 true, false},3427 3428 {R"(3429 define void @test() {3430 %a = alloca i323431 %r = getelementptr i32, ptr %a, i32 03432 ret void3433 })",3434 true, true},3435 3436 {R"(3437 define void @test(i1 %cond) {3438 entry:3439 %a = alloca i323440 br label %bb13441 3442 bb1:3443 %r = phi ptr [ %a, %entry ], [ %r, %bb1 ]3444 br i1 %cond, label %bb1, label %exit3445 3446 exit:3447 ret void3448 })",3449 true, true},3450 3451 {R"(3452 define void @test(i1 %cond) {3453 %a = alloca i323454 %r = select i1 %cond, ptr %a, ptr %a3455 ret void3456 })",3457 true, true},3458 3459 {R"(3460 define void @test(i1 %cond) {3461 %a = alloca i323462 %b = alloca i323463 %r = select i1 %cond, ptr %a, ptr %b3464 ret void3465 })",3466 false, false},3467 3468 {R"(3469 define void @test(i1 %cond) {3470 entry:3471 %a = alloca i643472 %a32 = bitcast ptr %a to ptr3473 br label %bb13474 3475 bb1:3476 %x = phi ptr [ %a32, %entry ], [ %x, %bb1 ]3477 %r = getelementptr i32, ptr %x, i32 13478 br i1 %cond, label %bb1, label %exit3479 3480 exit:3481 ret void3482 })",3483 true, false},3484 3485 {R"(3486 define void @test(i1 %cond) {3487 entry:3488 %a = alloca i643489 %a32 = bitcast ptr %a to ptr3490 br label %bb13491 3492 bb1:3493 %x = phi ptr [ %a32, %entry ], [ %r, %bb1 ]3494 %r = getelementptr i32, ptr %x, i32 13495 br i1 %cond, label %bb1, label %exit3496 3497 exit:3498 ret void3499 })",3500 true, false},3501 3502 {R"(3503 define void @test(i1 %cond, ptr %a) {3504 entry:3505 %r = bitcast ptr %a to ptr3506 ret void3507 })",3508 false, false},3509 3510 {R"(3511 define void @test(i1 %cond) {3512 entry:3513 %a = alloca i323514 %b = alloca i323515 br label %bb13516 3517 bb1:3518 %r = phi ptr [ %a, %entry ], [ %b, %bb1 ]3519 br i1 %cond, label %bb1, label %exit3520 3521 exit:3522 ret void3523 })",3524 false, false},3525 {R"(3526 declare ptr @retptr(ptr returned)3527 define void @test(i1 %cond) {3528 %a = alloca i323529 %r = call ptr @retptr(ptr %a)3530 ret void3531 })",3532 true, true},3533 {R"(3534 declare ptr @fun(ptr)3535 define void @test(i1 %cond) {3536 %a = alloca i323537 %r = call ptr @fun(ptr %a)3538 ret void3539 })",3540 false, false},3541};3542 3543TEST_P(FindAllocaForValueTest, findAllocaForValue) {3544 auto M = parseModule(GetParam().IR);3545 Function *F = M->getFunction("test");3546 Instruction *I = &findInstructionByName(F, "r");3547 const AllocaInst *AI = findAllocaForValue(I);3548 EXPECT_EQ(!!AI, GetParam().AnyOffsetResult);3549}3550 3551TEST_P(FindAllocaForValueTest, findAllocaForValueZeroOffset) {3552 auto M = parseModule(GetParam().IR);3553 Function *F = M->getFunction("test");3554 Instruction *I = &findInstructionByName(F, "r");3555 const AllocaInst *AI = findAllocaForValue(I, true);3556 EXPECT_EQ(!!AI, GetParam().ZeroOffsetResult);3557}3558 3559INSTANTIATE_TEST_SUITE_P(FindAllocaForValueTest, FindAllocaForValueTest,3560 ::testing::ValuesIn(FindAllocaForValueTests));3561