[EarlyCSE] Retain poison flags, if program is UB if poison.
authorFlorian Hahn <flo@fhahn.com>
Sat, 11 Dec 2021 13:44:14 +0000 (13:44 +0000)
committerFlorian Hahn <flo@fhahn.com>
Sat, 11 Dec 2021 15:11:44 +0000 (15:11 +0000)
Poison-generating flags can be retained during CSE on the earlier
instruction , *if* the earlier instruction being poison causes UB. For
now, always take AND for floating point instructions.

https://alive2.llvm.org/ce/z/4K3D7P

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D115247

llvm/lib/Transforms/Scalar/EarlyCSE.cpp
llvm/test/Transforms/EarlyCSE/flags.ll

index 90f71f7..a24997d 100644 (file)
@@ -1366,8 +1366,16 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
           LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
           continue;
         }
-        if (auto *I = dyn_cast<Instruction>(V))
-          I->andIRFlags(&Inst);
+        if (auto *I = dyn_cast<Instruction>(V)) {
+          // If I being poison triggers UB, there is no need to drop those
+          // flags. Otherwise, only retain flags present on both I and Inst.
+          // TODO: Currently some fast-math flags are not treated as
+          // poison-generating even though they should. Until this is fixed,
+          // always retain flags present on both I and Inst for floating point
+          // instructions.
+          if (isa<FPMathOperator>(I) || (I->hasPoisonGeneratingFlags() && !programUndefinedIfPoison(I)))
+            I->andIRFlags(&Inst);
+        }
         Inst.replaceAllUsesWith(V);
         salvageKnowledge(&Inst, &AC);
         removeMSSA(Inst);
index 5434db9..487ef5e 100644 (file)
@@ -22,7 +22,7 @@ declare void @use.i8(i8*)
 
 define void @test_inbounds_program_ub_if_first_gep_poison(i8* %ptr, i64 %n) {
 ; CHECK-LABEL: @test_inbounds_program_ub_if_first_gep_poison(
-; CHECK-NEXT:    [[ADD_PTR_1:%.*]] = getelementptr i8, i8* [[PTR:%.*]], i64 [[N:%.*]]
+; CHECK-NEXT:    [[ADD_PTR_1:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i64 [[N:%.*]]
 ; CHECK-NEXT:    call void @use.i8(i8* noundef [[ADD_PTR_1]])
 ; CHECK-NEXT:    call void @use.i8(i8* [[ADD_PTR_1]])
 ; CHECK-NEXT:    ret void