Răsfoiți Sursa

[spirv] Optimize IfStmt codegen for const-eval'able conditions (#567)

Lei Zhang 8 ani în urmă
părinte
comite
d4f8ffaab6

+ 12 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -851,6 +851,18 @@ void SPIRVEmitter::doIfStmt(const IfStmt *ifStmt) {
   //         +-> | merge | <-+                  +---> | merge |
   //         +-> | merge | <-+                  +---> | merge |
   //             +-------+                            +-------+
   //             +-------+                            +-------+
 
 
+  { // Try to see if we can const-eval the condition
+    bool condition = false;
+    if (ifStmt->getCond()->EvaluateAsBooleanCondition(condition, astContext)) {
+      if (condition) {
+        doStmt(ifStmt->getThen());
+      } else if (ifStmt->getElse()) {
+        doStmt(ifStmt->getElse());
+      }
+      return;
+    }
+  }
+
   if (const auto *declStmt = ifStmt->getConditionVariableDeclStmt())
   if (const auto *declStmt = ifStmt->getConditionVariableDeclStmt())
     doDeclStmt(declStmt);
     doDeclStmt(declStmt);
 
 

+ 26 - 0
tools/clang/test/CodeGenSPIRV/if-stmt.const-cond.hlsl

@@ -0,0 +1,26 @@
+// Run: %dxc -T vs_6_0 -E main
+
+void main(out float a: A, out float b: B) {
+// CHECK-LABEL: %bb_entry = OpLabel
+    if (3 + 5) {
+// CHECK-NEXT: OpStore %a %float_1
+        a = 1.0;
+    } else {
+        a = 0.0;
+    }
+
+    if (4 + 3 > 7 || 4 + 3 < 8) {
+// CHECK-NEXT: OpStore %b %float_2
+        b = 2.0;
+    }
+
+    if (4 + 3 > 7 && true) {
+        b = 0.0;
+    }
+
+    if (true)
+        ;
+
+    if (false) {}
+// CHECK-NEXT: OpReturn
+}

+ 0 - 3
tools/clang/test/CodeGenSPIRV/if-stmt.plain.hlsl

@@ -1,8 +1,5 @@
 // Run: %dxc -T ps_6_0 -E main
 // Run: %dxc -T ps_6_0 -E main
 
 
-// Note: we need to consider the order of basic blocks. So CHECK-NEXT is used
-// extensively.
-
 void main() {
 void main() {
 // CHECK-LABEL: %bb_entry = OpLabel
 // CHECK-LABEL: %bb_entry = OpLabel
     bool c;
     bool c;

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -204,6 +204,9 @@ TEST_F(FileTest, CastSplatMatrix) { runFileTest("cast.matrix.splat.hlsl"); }
 // For if statements
 // For if statements
 TEST_F(FileTest, IfStmtPlainAssign) { runFileTest("if-stmt.plain.hlsl"); }
 TEST_F(FileTest, IfStmtPlainAssign) { runFileTest("if-stmt.plain.hlsl"); }
 TEST_F(FileTest, IfStmtNestedIfStmt) { runFileTest("if-stmt.nested.hlsl"); }
 TEST_F(FileTest, IfStmtNestedIfStmt) { runFileTest("if-stmt.nested.hlsl"); }
+TEST_F(FileTest, IfStmtConstCondition) {
+  runFileTest("if-stmt.const-cond.hlsl");
+}
 
 
 // For switch statements
 // For switch statements
 TEST_F(FileTest, SwitchStmtUsingOpSwitch) {
 TEST_F(FileTest, SwitchStmtUsingOpSwitch) {