فهرست منبع

Special ICB variables for nops are now arrays for driver compat. (#2774)

Adam Yang 5 سال پیش
والد
کامیت
43122fc20b

+ 58 - 29
lib/HLSL/DxilNoops.cpp

@@ -103,8 +103,8 @@ using namespace llvm;
 namespace {
 StringRef kNoopName = "dx.noop";
 StringRef kPreservePrefix = "dx.preserve.";
-StringRef kNothingName = "dx.nothing";
-StringRef kPreserveName = "dx.preserve.value";
+StringRef kNothingName = "dx.nothing.a";
+StringRef kPreserveName = "dx.preserve.value.a";
 }
 
 static Function *GetOrCreateNoopF(Module &M) {
@@ -115,6 +115,12 @@ static Function *GetOrCreateNoopF(Module &M) {
   return NoopF;
 }
 
+static Constant *GetConstGep(Constant *Ptr, unsigned Idx0, unsigned Idx1) {
+  Type *i32Ty = Type::getInt32Ty(Ptr->getContext());
+  Constant *Indices[] = { ConstantInt::get(i32Ty, Idx0), ConstantInt::get(i32Ty, Idx1) };
+  return ConstantExpr::getGetElementPtr(nullptr, Ptr, Indices);
+}
+
 static bool ShouldPreserve(Value *V) {
   if (isa<Constant>(V)) return true;
   if (isa<Argument>(V)) return true;
@@ -190,6 +196,14 @@ static void FindAllStores(Value *Ptr, std::vector<Store_Info> *Stores, std::vect
   }
 }
 
+static User *GetUniqueUser(Value *V) {
+  if (V->user_begin() != V->user_end()) {
+    if (std::next(V->user_begin()) == V->user_end())
+      return *V->user_begin();
+  }
+  return nullptr;
+}
+
 static Value *GetOrCreatePreserveCond(Function *F) {
   assert(!F->isDeclaration());
 
@@ -197,19 +211,24 @@ static Value *GetOrCreatePreserveCond(Function *F) {
   GlobalVariable *GV = M->getGlobalVariable(kPreserveName, true);
   if (!GV) {
     Type *i32Ty = Type::getInt32Ty(M->getContext());
+    Type *i32ArrayTy = ArrayType::get(i32Ty, 1);
+
+    unsigned int Values[1] = { 0 };
+    Constant *InitialValue = llvm::ConstantDataArray::get(M->getContext(), Values);
+
     GV = new GlobalVariable(*M,
-      i32Ty, true,
+      i32ArrayTy, true,
       llvm::GlobalValue::InternalLinkage,
-      llvm::ConstantInt::get(i32Ty, 0), kPreserveName);
+      InitialValue, kPreserveName);
   }
 
   for (User *U : GV->users()) {
-    LoadInst *LI = cast<LoadInst>(U);
-    if (LI->getParent()->getParent() == F) {
-      assert(LI->user_begin() != LI->user_end() &&
-        std::next(LI->user_begin()) == LI->user_end());
-
-      return *LI->user_begin();
+    GEPOperator *Gep = Gep = cast<GEPOperator>(U);
+    for (User *GepU : Gep->users()) {
+      LoadInst *LI = cast<LoadInst>(GepU);
+      if (LI->getParent()->getParent() == F) {
+        return GetUniqueUser(LI);
+      }
     }
   }
 
@@ -220,7 +239,8 @@ static Value *GetOrCreatePreserveCond(Function *F) {
 
   IRBuilder<> B(InsertPt);
 
-  LoadInst *Load = B.CreateLoad(GV);
+  Constant *Gep = GetConstGep(GV, 0, 0);
+  LoadInst *Load = B.CreateLoad(Gep);
   return B.CreateTrunc(Load, B.getInt1Ty());
 }
 
@@ -461,18 +481,24 @@ public:
   }
 
   Instruction *GetFinalNoopInst(Module &M, Instruction *InsertBefore) {
+    Type *i32Ty = Type::getInt32Ty(M.getContext());
     if (!NothingGV) {
       NothingGV = M.getGlobalVariable(kNothingName);
       if (!NothingGV) {
-        Type *i32Ty = Type::getInt32Ty(M.getContext());
+        Type *i32ArrayTy = ArrayType::get(i32Ty, 1);
+
+        unsigned int Values[1] = { 0 };
+        Constant *InitialValue = llvm::ConstantDataArray::get(M.getContext(), Values);
+
         NothingGV = new GlobalVariable(M,
-          i32Ty, true,
+          i32ArrayTy, true,
           llvm::GlobalValue::InternalLinkage,
-          llvm::ConstantInt::get(i32Ty, 0), kNothingName);
+          InitialValue, kNothingName);
       }
     }
 
-    return new llvm::LoadInst(NothingGV, nullptr, InsertBefore);
+    Constant *Gep = GetConstGep(NothingGV, 0, 0);
+    return new llvm::LoadInst(Gep, nullptr, InsertBefore);
   }
 
   bool LowerPreserves(Module &M);
@@ -491,20 +517,23 @@ bool DxilFinalizePreserves::LowerPreserves(Module &M) {
   GlobalVariable *GV = M.getGlobalVariable(kPreserveName, true);
   if (GV) {
     for (User *U : GV->users()) {
-      LoadInst *LI = cast<LoadInst>(U);
-      assert(LI->user_begin() != LI->user_end() &&
-        std::next(LI->user_begin()) == LI->user_end());
-      Instruction *I = cast<Instruction>(*LI->user_begin());
-
-      for (User *UU : I->users()) {
-
-        SelectInst *P = cast<SelectInst>(UU);
-        Value *PrevV = P->getTrueValue();
-        Value *CurV = P->getFalseValue();
-
-        if (isa<UndefValue>(PrevV) || isa<Constant>(PrevV)) {
-          P->setOperand(1, CurV);
-          Changed = true;
+      GEPOperator *Gep = cast<GEPOperator>(U);
+      for (User *GepU : Gep->users()) {
+        LoadInst *LI = cast<LoadInst>(GepU);
+        assert(LI->user_begin() != LI->user_end() &&
+          std::next(LI->user_begin()) == LI->user_end());
+        Instruction *I = cast<Instruction>(*LI->user_begin());
+
+        for (User *UU : I->users()) {
+
+          SelectInst *P = cast<SelectInst>(UU);
+          Value *PrevV = P->getTrueValue();
+          Value *CurV = P->getFalseValue();
+
+          if (isa<UndefValue>(PrevV) || isa<Constant>(PrevV)) {
+            P->setOperand(1, CurV);
+            Changed = true;
+          }
         }
       }
     }

BIN
projects/dxilconv/test/regression_tests/AppendStructuredBuffer.fxc


BIN
projects/dxilconv/test/regression_tests/ConsumeStructuredBuffer.fxc


BIN
projects/dxilconv/test/regression_tests/UpdateCounter.fxc


+ 6 - 3
tools/clang/test/HLSLFileCheck/dxil/debug/noop_no_fold_double.hlsl

@@ -7,7 +7,8 @@ Texture2D tex1 : register(t1);
 
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
 float4 main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   double x = 10;
@@ -26,12 +27,14 @@ float4 main() : SV_Target {
   // select i1 %[[p]], double [[c1]], double [[c1]]
 
   Texture2D tex = tex0; 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK-SAME: @dx.nothing
 
   // CHECK: br i1
   if (w >= 0) {
     tex = tex1;
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: br
   }
 

+ 6 - 3
tools/clang/test/HLSLFileCheck/dxil/debug/noop_no_fold_int.hlsl

@@ -7,7 +7,8 @@ Texture2D tex1 : register(t1);
 
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
 float4 main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   int x = 10;
@@ -28,12 +29,14 @@ float4 main() : SV_Target {
   // select i1 %[[p]], i32 [[c1]], i32 [[c1]]
 
   Texture2D tex = tex0; 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK-SAME: @dx.nothing
 
   // CHECK: br i1
   if (w >= 0) {
     tex = tex1;
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: br
   }
 

+ 14 - 7
tools/clang/test/HLSLFileCheck/dxil/debug/noop_out_args.hlsl

@@ -25,28 +25,35 @@ void baz(inout float x, inout float y) {
 
 [RootSignature("")]
 float main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   S s;
 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK: @dx.nothing
   foo(s);
     // CHECK: select i1 %[[p]]
     // CHECK: select i1 %[[p]]
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK: @dx.nothing
 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK: @dx.nothing
   bar(s);
     // CHECK: fmul
     // CHECK: fmul
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK: @dx.nothing
 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK: @dx.nothing
   baz(s.x, s.y);
     // CHECK: fmul
     // CHECK: fmul
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK: @dx.nothing
 
   // CHECK: fadd
   return s.x + s.y;

+ 10 - 5
tools/clang/test/HLSLFileCheck/dxil/debug/noop_resource_var.hlsl

@@ -19,20 +19,25 @@ void store_things() {
 [numthreads(1, 1, 1)]
 [RootSignature("CBV(b0), DescriptorTable(UAV(u0))")]
 void main() {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK: @dx.nothing
   my_uav = uav;
 
   // select i1 [[p]],
   float ret = foo;
 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK: @dx.nothing
   store_things();
     // CHECK: unary.f32(i32 13
-    // CHECK: load i32, i32* @dx.nothing
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK: @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK: @dx.nothing
     // CHECK: call void @dx.op.bufferStore.f32(
 
   // CHECK: call void @dx.op.bufferStore.f32(

+ 4 - 2
tools/clang/test/HLSLFileCheck/dxil/debug/noop_void_return.hlsl

@@ -9,14 +9,16 @@ void foo() {
 
 [RootSignature("")]
 float main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   // CHECK: select i1 %[[p]]
   my_glob = 0;
 
   // Function call
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK: @dx.nothing
   foo();
     // CHECK: select i1 %[[p]]
     // void return

+ 22 - 13
tools/clang/test/HLSLFileCheck/dxil/debug/noops_call.hlsl

@@ -60,16 +60,16 @@ float4 depth2(float4 val)
     return val;
 }
 
-// CHECK: @dx.nothing = internal constant i32 0
-
 [RootSignature("")]
 float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
 {
-    // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+    // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+    // CHECK-SAME: @dx.preserve.value
     // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
     float4 ret1 = localScopeVar_func(color);
     // ** call **
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: %[[v1:.+]] = fmul
     // CHECK: %[[v2:.+]] = fmul
     // CHECK: %[[v3:.+]] = fmul
@@ -82,7 +82,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
 
     float4 ret2 = localRegVar_func(ret1);
     // ** call **
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // ** copy **
     // CHECK: select i1 %[[p]],
     // CHECK: select i1 %[[p]],
@@ -92,7 +93,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
 
     float4 ret3 = array_func(ret2);
     // ** call **
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: store
     // CHECK: store
     // CHECK: store
@@ -105,7 +107,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
 
     float4 ret4 = typedef_func(ret3);
     // ** call **
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // ** copy **
     // CHECK: select i1 %[[p]], float %{{.+}}
     // CHECK: select i1 %[[p]], float %{{.+}}
@@ -115,7 +118,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
 
     float4 ret5 = global_func(ret4);
     // ** call **
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: %[[a1:.+]] = fmul
     // CHECK: %[[a2:.+]] = fmul
     // CHECK: %[[a3:.+]] = fmul
@@ -128,25 +132,30 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
 
     float4 ret6 = depth2(ret5);
     // ** call **
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // depth2() {
       // ** call **
-      // CHECK: load i32, i32* @dx.nothing
+      // CHECK: load i32, i32*
+      // CHECK-SAME: @dx.nothing
       // depth3() {
         // ** call **
-        // CHECK: load i32, i32* @dx.nothing
+        // CHECK: load i32, i32*
+        // CHECK-SAME: @dx.nothing
         // depth4() {
           // CHECK: %[[b1:.+]] = fmul
           // CHECK: %[[b2:.+]] = fmul
           // CHECK: %[[b3:.+]] = fmul
           // CHECK: %[[b4:.+]] = fmul
-          // CHECK: load i32, i32* @dx.nothing
+          // CHECK: load i32, i32*
+          // CHECK-SAME: @dx.nothing
         // }
         // CHECK: %[[c1:.+]] = fmul
         // CHECK: %[[c2:.+]] = fmul
         // CHECK: %[[c3:.+]] = fmul
         // CHECK: %[[c4:.+]] = fmul
-        // CHECK: load i32, i32* @dx.nothing
+        // CHECK: load i32, i32*
+        // CHECK-SAME: @dx.nothing
       // }
       // CHECK: %[[d1:.+]] = fmul
       // CHECK: %[[d2:.+]] = fmul

+ 2 - 1
tools/clang/test/HLSLFileCheck/dxil/debug/noops_groupshare.hlsl

@@ -13,7 +13,8 @@ groupshared float bar;
 [RootSignature("CBV(b0), DescriptorTable(UAV(u0))")]
 void main() {
 
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   // CHECK: store

+ 2 - 1
tools/clang/test/HLSLFileCheck/dxil/debug/noops_mandatory_immed.hlsl

@@ -9,7 +9,8 @@ SamplerState samp0 : register(s0);
 
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1)), DescriptorTable(Sampler(s0))")]
 float4 main(float2 uv : TEXCOORD) : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   int a = -8;

+ 2 - 1
tools/clang/test/HLSLFileCheck/dxil/debug/noops_mandatory_immed_load.hlsl

@@ -16,7 +16,8 @@ SamplerState samp0 : register(s0);
 
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1)), DescriptorTable(Sampler(s0))")]
 float4 main(float2 uv : TEXCOORD) : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   int a = 1;

+ 4 - 2
tools/clang/test/HLSLFileCheck/dxil/debug/noops_memcpy.hlsl

@@ -6,7 +6,8 @@ struct S {
 };
 
 float main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   S a = { 0.f, 1.f};
@@ -23,7 +24,8 @@ float main() : SV_Target {
 
   S d = c;
   // Memcpy should just get lowered to a noop for now.
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK-SAME: @dx.nothing
 
   return d.x + d.y;
 }

+ 6 - 3
tools/clang/test/HLSLFileCheck/dxil/debug/noops_no_fold.hlsl

@@ -7,7 +7,8 @@ Texture2D tex1 : register(t1);
 
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
 float4 main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   float x = 10;
@@ -26,12 +27,14 @@ float4 main() : SV_Target {
   // select i1 %[[p]], float [[c1]], float [[c1]]
 
   Texture2D tex = tex0; 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK-SAME: @dx.nothing
 
   // CHECK: br i1
   if (w >= 0) {
     tex = tex1;
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: br
   }
 

+ 6 - 5
tools/clang/test/HLSLFileCheck/dxil/debug/noops_no_fold_vec.hlsl

@@ -5,11 +5,10 @@
 Texture2D tex0 : register(t0);
 Texture2D tex1 : register(t1);
 
-// CHECK: @dx.nothing = internal constant i32 0
-
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
 float4 main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   float2 xy = float2(10, 20);
@@ -35,12 +34,14 @@ float4 main() : SV_Target {
   // select i1 %[[p]], float [[c2]], float [[c2]]
 
   Texture2D tex = tex0; 
-  // CHECK: load i32, i32* @dx.nothing
+  // CHECK: load i32, i32*
+  // CHECK-SAME: @dx.nothing
 
   // CHECK: br i1
   if (foo.x+bar.y >= 0) {
     tex = tex1;
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
     // CHECK: br
   }
 

+ 6 - 3
tools/clang/test/HLSLFileCheck/dxil/debug/noops_simple_call.hlsl

@@ -5,13 +5,16 @@ float foo(float arg) {
 }
 
 float main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   float x = 10; // CHECK: %[[x:.+]] = select i1 %[[p]], float 1.000000e+01, float 1.000000e+01
-  float y = foo(x); // CHECK: load i32, i32* @dx.nothing
+  float y = foo(x); // CHECK: load i32, i32*
+  // CHECK-SAME: @dx.nothing
     // Return
-    // CHECK: load i32, i32* @dx.nothing
+    // CHECK: load i32, i32*
+    // CHECK-SAME: @dx.nothing
   // CHECK: %[[y:.+]] = select i1 %[[p]], float %[[x]], float %[[x]]
 
   return y;

+ 2 - 1
tools/clang/test/HLSLFileCheck/dxil/debug/preserve_rewrite.hlsl

@@ -5,7 +5,8 @@ Texture2D tex1 : register(t1);
 
 [RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
 float main() : SV_Target {
-  // CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
+  // CHECK: %[[p_load:[0-9]+]] = load i32, i32*
+  // CHECK-SAME: @dx.preserve.value
   // CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
 
   int x = 10;