[Local] Preserve !invariant.load of dominating instruction
authorNikita Popov <npopov@redhat.com>
Mon, 3 Apr 2023 14:03:11 +0000 (16:03 +0200)
committerNikita Popov <npopov@redhat.com>
Mon, 3 Apr 2023 14:05:02 +0000 (16:05 +0200)
Per LangRef:

> If a load instruction tagged with the !invariant.load metadata
> is executed, the memory location referenced by the load has to
> contain the same value at all points in the program where the
> memory location is dereferenceable; otherwise, the behavior is
> undefined.

As invariant.load violation is immediate undefined behavior, it
is sufficient for it to be present on the dominating load (for
the case where K does not move).

llvm/lib/Transforms/Utils/Local.cpp
llvm/test/Transforms/GVN/PRE/invariant-load.ll

index b32ed2a..c0d9569 100644 (file)
@@ -2682,8 +2682,10 @@ void llvm::combineMetadata(Instruction *K, const Instruction *J,
         K->setMetadata(Kind, MDNode::getMostGenericFPMath(JMD, KMD));
         break;
       case LLVMContext::MD_invariant_load:
-        // Only set the !invariant.load if it is present in both instructions.
-        K->setMetadata(Kind, JMD);
+        // If K moves, only set the !invariant.load if it is present in both
+        // instructions.
+        if (DoesKMove)
+          K->setMetadata(Kind, JMD);
         break;
       case LLVMContext::MD_nonnull:
         if (DoesKMove || !K->hasMetadata(LLVMContext::MD_noundef))
index 3d01026..79cf951 100644 (file)
@@ -187,7 +187,7 @@ define i32 @metadata_preservation(ptr nocapture %p, ptr nocapture %q) {
 ; CHECK-LABEL: define i32 @metadata_preservation
 ; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr nocapture [[Q:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !0
 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], [[X]]
 ; CHECK-NEXT:    ret i32 [[ADD]]
 ;