1 //===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Analysis/ValueTracking.h" 11 #include "llvm/AsmParser/Parser.h" 12 #include "llvm/IR/Function.h" 13 #include "llvm/IR/InstIterator.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/Support/ErrorHandling.h" 17 #include "llvm/Support/SourceMgr.h" 18 #include "gtest/gtest.h" 19 20 using namespace llvm; 21 22 namespace { 23 24 class MatchSelectPatternTest : public testing::Test { 25 protected: 26 void parseAssembly(const char *Assembly) { 27 SMDiagnostic Error; 28 M = parseAssemblyString(Assembly, Error, Context); 29 30 std::string errMsg; 31 raw_string_ostream os(errMsg); 32 Error.print("", os); 33 34 // A failure here means that the test itself is buggy. 35 if (!M) 36 report_fatal_error(os.str()); 37 38 Function *F = M->getFunction("test"); 39 if (F == nullptr) 40 report_fatal_error("Test must have a function named @test"); 41 42 A = nullptr; 43 for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 44 if (I->hasName()) { 45 if (I->getName() == "A") 46 A = &*I; 47 } 48 } 49 if (A == nullptr) 50 report_fatal_error("@test must have an instruction %A"); 51 } 52 53 void expectPattern(const SelectPatternResult &P) { 54 Value *LHS, *RHS; 55 Instruction::CastOps CastOp; 56 SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp); 57 EXPECT_EQ(P.Flavor, R.Flavor); 58 EXPECT_EQ(P.NaNBehavior, R.NaNBehavior); 59 EXPECT_EQ(P.Ordered, R.Ordered); 60 } 61 62 LLVMContext Context; 63 std::unique_ptr<Module> M; 64 Instruction *A, *B; 65 }; 66 67 } 68 69 TEST_F(MatchSelectPatternTest, SimpleFMin) { 70 parseAssembly( 71 "define float @test(float %a) {\n" 72 " %1 = fcmp ult float %a, 5.0\n" 73 " %A = select i1 %1, float %a, float 5.0\n" 74 " ret float %A\n" 75 "}\n"); 76 expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 77 } 78 79 TEST_F(MatchSelectPatternTest, SimpleFMax) { 80 parseAssembly( 81 "define float @test(float %a) {\n" 82 " %1 = fcmp ogt float %a, 5.0\n" 83 " %A = select i1 %1, float %a, float 5.0\n" 84 " ret float %A\n" 85 "}\n"); 86 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 87 } 88 89 TEST_F(MatchSelectPatternTest, SwappedFMax) { 90 parseAssembly( 91 "define float @test(float %a) {\n" 92 " %1 = fcmp olt float 5.0, %a\n" 93 " %A = select i1 %1, float %a, float 5.0\n" 94 " ret float %A\n" 95 "}\n"); 96 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); 97 } 98 99 TEST_F(MatchSelectPatternTest, SwappedFMax2) { 100 parseAssembly( 101 "define float @test(float %a) {\n" 102 " %1 = fcmp olt float %a, 5.0\n" 103 " %A = select i1 %1, float 5.0, float %a\n" 104 " ret float %A\n" 105 "}\n"); 106 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); 107 } 108 109 TEST_F(MatchSelectPatternTest, SwappedFMax3) { 110 parseAssembly( 111 "define float @test(float %a) {\n" 112 " %1 = fcmp ult float %a, 5.0\n" 113 " %A = select i1 %1, float 5.0, float %a\n" 114 " ret float %A\n" 115 "}\n"); 116 expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 117 } 118 119 TEST_F(MatchSelectPatternTest, FastFMin) { 120 parseAssembly( 121 "define float @test(float %a) {\n" 122 " %1 = fcmp nnan olt float %a, 5.0\n" 123 " %A = select i1 %1, float %a, float 5.0\n" 124 " ret float %A\n" 125 "}\n"); 126 expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false}); 127 } 128 129 TEST_F(MatchSelectPatternTest, FMinConstantZero) { 130 parseAssembly( 131 "define float @test(float %a) {\n" 132 " %1 = fcmp ole float %a, 0.0\n" 133 " %A = select i1 %1, float %a, float 0.0\n" 134 " ret float %A\n" 135 "}\n"); 136 // This shouldn't be matched, as %a could be -0.0. 137 expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 138 } 139 140 TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) { 141 parseAssembly( 142 "define float @test(float %a) {\n" 143 " %1 = fcmp nsz ole float %a, 0.0\n" 144 " %A = select i1 %1, float %a, float 0.0\n" 145 " ret float %A\n" 146 "}\n"); 147 // But this should be, because we've ignored signed zeroes. 148 expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 149 } 150 151 TEST_F(MatchSelectPatternTest, DoubleCastU) { 152 parseAssembly( 153 "define i32 @test(i8 %a, i8 %b) {\n" 154 " %1 = icmp ult i8 %a, %b\n" 155 " %2 = zext i8 %a to i32\n" 156 " %3 = zext i8 %b to i32\n" 157 " %A = select i1 %1, i32 %2, i32 %3\n" 158 " ret i32 %A\n" 159 "}\n"); 160 // We should be able to look through the situation where we cast both operands 161 // to the select. 162 expectPattern({SPF_UMIN, SPNB_NA, false}); 163 } 164 165 TEST_F(MatchSelectPatternTest, DoubleCastS) { 166 parseAssembly( 167 "define i32 @test(i8 %a, i8 %b) {\n" 168 " %1 = icmp slt i8 %a, %b\n" 169 " %2 = sext i8 %a to i32\n" 170 " %3 = sext i8 %b to i32\n" 171 " %A = select i1 %1, i32 %2, i32 %3\n" 172 " ret i32 %A\n" 173 "}\n"); 174 // We should be able to look through the situation where we cast both operands 175 // to the select. 176 expectPattern({SPF_SMIN, SPNB_NA, false}); 177 } 178 179 TEST_F(MatchSelectPatternTest, DoubleCastBad) { 180 parseAssembly( 181 "define i32 @test(i8 %a, i8 %b) {\n" 182 " %1 = icmp ult i8 %a, %b\n" 183 " %2 = zext i8 %a to i32\n" 184 " %3 = sext i8 %b to i32\n" 185 " %A = select i1 %1, i32 %2, i32 %3\n" 186 " ret i32 %A\n" 187 "}\n"); 188 // The cast types here aren't the same, so we cannot match an UMIN. 189 expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 190 } 191 192 TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) { 193 StringRef Assembly = 194 "declare void @nounwind_readonly(i32*) nounwind readonly " 195 "declare void @nounwind_argmemonly(i32*) nounwind argmemonly " 196 "declare void @throws_but_readonly(i32*) readonly " 197 "declare void @throws_but_argmemonly(i32*) argmemonly " 198 " " 199 "declare void @unknown(i32*) " 200 " " 201 "define void @f(i32* %p) { " 202 " call void @nounwind_readonly(i32* %p) " 203 " call void @nounwind_argmemonly(i32* %p) " 204 " call void @throws_but_readonly(i32* %p) " 205 " call void @throws_but_argmemonly(i32* %p) " 206 " call void @unknown(i32* %p) nounwind readonly " 207 " call void @unknown(i32* %p) nounwind argmemonly " 208 " call void @unknown(i32* %p) readonly " 209 " call void @unknown(i32* %p) argmemonly " 210 " ret void " 211 "} "; 212 213 LLVMContext Context; 214 SMDiagnostic Error; 215 auto M = parseAssemblyString(Assembly, Error, Context); 216 assert(M && "Bad assembly?"); 217 218 auto *F = M->getFunction("f"); 219 assert(F && "Bad assembly?"); 220 221 auto &BB = F->getEntryBlock(); 222 ArrayRef<bool> ExpectedAnswers = { 223 true, // call void @nounwind_readonly(i32* %p) 224 true, // call void @nounwind_argmemonly(i32* %p) 225 false, // call void @throws_but_readonly(i32* %p) 226 false, // call void @throws_but_argmemonly(i32* %p) 227 true, // call void @unknown(i32* %p) nounwind readonly 228 true, // call void @unknown(i32* %p) nounwind argmemonly 229 false, // call void @unknown(i32* %p) readonly 230 false, // call void @unknown(i32* %p) argmemonly 231 false, // ret void 232 }; 233 234 int Index = 0; 235 for (auto &I : BB) { 236 EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I), 237 ExpectedAnswers[Index]) 238 << "Incorrect answer at instruction " << Index << " = " << I; 239 Index++; 240 } 241 } 242