Create a separate header and source file for each pass.
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index 1c98bdc..01e7fdb 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -2,26 +2,33 @@
   basic_block.h
   constants.h
   def_use_manager.h
+  eliminate_dead_constant_pass.h
   function.h
+  fold_spec_constant_op_and_composite_pass.h
+  freeze_spec_constant_value_pass.h
   instruction.h
   ir_loader.h
   libspirv.hpp
   module.h
+  null_pass.h
   reflect.h
   pass.h
   passes.h
   pass_manager.h
+  strip_debug_info_pass.h
   types.h
   type_manager.h
 
   def_use_manager.cpp
+  eliminate_dead_constant_pass.cpp
   function.cpp
-  fold_spec_const_op_composite.cpp
+  fold_spec_constant_op_and_composite_pass.cpp
+  freeze_spec_constant_value_pass.cpp
   instruction.cpp
   ir_loader.cpp
   libspirv.cpp
   module.cpp
-  passes.cpp
+  strip_debug_info_pass.cpp
   types.cpp
   type_manager.cpp
 )
diff --git a/source/opt/passes.cpp b/source/opt/eliminate_dead_constant_pass.cpp
similarity index 79%
rename from source/opt/passes.cpp
rename to source/opt/eliminate_dead_constant_pass.cpp
index 4698950..575cfbd 100644
--- a/source/opt/passes.cpp
+++ b/source/opt/eliminate_dead_constant_pass.cpp
@@ -24,60 +24,18 @@
 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 
-#include "passes.h"
+#include "eliminate_dead_constant_pass.h"
 
 #include <algorithm>
-#include <iostream>
 #include <unordered_map>
 #include <unordered_set>
 
+#include "def_use_manager.h"
 #include "reflect.h"
 
 namespace spvtools {
 namespace opt {
 
-bool StripDebugInfoPass::Process(ir::Module* module) {
-  bool modified = !module->debugs().empty();
-  module->debug_clear();
-
-  module->ForEachInst([&modified](ir::Instruction* inst) {
-    modified |= !inst->dbg_line_insts().empty();
-    inst->dbg_line_insts().clear();
-  });
-
-  return modified;
-}
-
-bool FreezeSpecConstantValuePass::Process(ir::Module* module) {
-  bool modified = false;
-  module->ForEachInst([&modified](ir::Instruction* inst) {
-    switch (inst->opcode()) {
-      case SpvOp::SpvOpSpecConstant:
-        inst->SetOpcode(SpvOp::SpvOpConstant);
-        modified = true;
-        break;
-      case SpvOp::SpvOpSpecConstantTrue:
-        inst->SetOpcode(SpvOp::SpvOpConstantTrue);
-        modified = true;
-        break;
-      case SpvOp::SpvOpSpecConstantFalse:
-        inst->SetOpcode(SpvOp::SpvOpConstantFalse);
-        modified = true;
-        break;
-      case SpvOp::SpvOpDecorate:
-        if (inst->GetSingleWordInOperand(1) ==
-            SpvDecoration::SpvDecorationSpecId) {
-          inst->ToNop();
-          modified = true;
-        }
-        break;
-      default:
-        break;
-    }
-  });
-  return modified;
-}
-
 bool EliminateDeadConstantPass::Process(ir::Module* module) {
   analysis::DefUseManager def_use(module);
   std::unordered_set<ir::Instruction*> working_list;
diff --git a/source/opt/eliminate_dead_constant_pass.h b/source/opt/eliminate_dead_constant_pass.h
new file mode 100644
index 0000000..ebb4e1e
--- /dev/null
+++ b/source/opt/eliminate_dead_constant_pass.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef LIBSPIRV_OPT_ELIMINATE_DEAD_CONSTANT_PASS_H_
+#define LIBSPIRV_OPT_ELIMINATE_DEAD_CONSTANT_PASS_H_
+
+#include "module.h"
+#include "pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// The optimization pass to remove dead constants, including front-end
+// contants: defined by OpConstant, OpConstantComposite, OpConstantTrue and
+// OpConstantFalse; and spec constants: defined by OpSpecConstant,
+// OpSpecConstantComposite, OpSpecConstantTrue, OpSpecConstantFalse and
+// OpSpecConstantOp.
+class EliminateDeadConstantPass : public Pass {
+ public:
+  const char* name() const override { return "eliminate-dead-const"; }
+  bool Process(ir::Module*) override;
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // LIBSPIRV_OPT_ELIMINATE_DEAD_CONSTANT_PASS_H_
diff --git a/source/opt/fold_spec_const_op_composite.cpp b/source/opt/fold_spec_constant_op_and_composite_pass.cpp
similarity index 99%
rename from source/opt/fold_spec_const_op_composite.cpp
rename to source/opt/fold_spec_constant_op_and_composite_pass.cpp
index f0c78dd..5204108 100644
--- a/source/opt/fold_spec_const_op_composite.cpp
+++ b/source/opt/fold_spec_constant_op_and_composite_pass.cpp
@@ -24,7 +24,7 @@
 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 
-#include "passes.h"
+#include "fold_spec_constant_op_and_composite_pass.h"
 
 #include <initializer_list>
 #include <memory>
diff --git a/source/opt/fold_spec_constant_op_and_composite_pass.h b/source/opt/fold_spec_constant_op_and_composite_pass.h
new file mode 100644
index 0000000..a948b0d
--- /dev/null
+++ b/source/opt/fold_spec_constant_op_and_composite_pass.h
@@ -0,0 +1,219 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef LIBSPIRV_OPT_FOLD_SPEC_CONSTANT_OP_AND_COMPOSITE_PASS_H_
+#define LIBSPIRV_OPT_FOLD_SPEC_CONSTANT_OP_AND_COMPOSITE_PASS_H_
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "constants.h"
+#include "def_use_manager.h"
+#include "module.h"
+#include "pass.h"
+#include "type_manager.h"
+
+namespace spvtools {
+namespace opt {
+
+// The optimization pass that folds "Spec Constants", which are defined by
+// OpSpecConstantOp and OpSpecConstantComposite instruction, to "Normal
+// Constants", which are defined by OpConstantTrue, OpConstantFalse,
+// OpConstant, OpConstantNull and OpConstantComposite instructions. Note that
+// Spec Constants defined with OpSpecConstant, OpSpecConstantTrue and
+// OpSpecConstantFalse instructions are not handled, as these instructions
+// indicate their value are not determined and can be changed in future.  A
+// Spec Constant is foldable if all of its value(s) can be determined from the
+// module. For example, an Integer Spec Constant defined with OpSpecConstantOp
+// instruction can be folded if its value won't change later. This pass will
+// replace the original OpSpecContantOp instruction with an OpConstant
+// instruction. When folding composite type Spec Constants, new instructions
+// may be inserted to define the components of the composite constant first,
+// then the original Spec Constants will be replace with OpConstantComposite
+// instructions.
+// There are some operations not supported:
+//  OpSConvert, OpFConvert, OpQuantizeToF16 and all the operations under Kernel
+//  capability.
+// TODO(qining): Add support for the operations listed above.
+class FoldSpecConstantOpAndCompositePass : public Pass {
+ public:
+  FoldSpecConstantOpAndCompositePass()
+      : max_id_(0),
+        module_(nullptr),
+        def_use_mgr_(nullptr),
+        type_mgr_(nullptr),
+        id_to_const_val_() {}
+  const char* name() const override { return "fold-spec-const-op-composite"; }
+  bool Process(ir::Module* module) override {
+    Initialize(module);
+    return ProcessImpl(module);
+  };
+
+ private:
+  // Initializes the type manager, def-use manager and get the maximal id used
+  // in the module.
+  void Initialize(ir::Module* module) {
+    type_mgr_.reset(new analysis::TypeManager(*module));
+    def_use_mgr_.reset(new analysis::DefUseManager(module));
+    for (const auto& id_def : def_use_mgr_->id_to_defs()) {
+      max_id_ = std::max(max_id_, id_def.first);
+    }
+    module_ = module;
+  };
+
+  // The real entry of processing. Iterates through the types-constants-globals
+  // section of the given module, finds the Spec Constants defined with
+  // OpSpecConstantOp and OpSpecConstantComposite instructions. If the result
+  // value of those spec constants can be folded, fold them to their
+  // corresponding normal constants. Returns true if the module was modified.
+  bool ProcessImpl(ir::Module*);
+
+  // Processes the OpSpecConstantOp instruction pointed by the given
+  // instruction iterator, folds it to normal constants if possible. Returns
+  // true if the spec constant is folded to normal constants. New instructions
+  // will be inserted before the OpSpecConstantOp instruction pointed by the
+  // instruction iterator. The instruction iterator, which is passed by
+  // pointer, will still point to the original OpSpecConstantOp instruction. If
+  // folding is done successfully, the original OpSpecConstantOp instruction
+  // will be changed to Nop and new folded instruction will be inserted before
+  // it.
+  bool ProcessOpSpecConstantOp(ir::Module::inst_iterator* pos);
+
+  // Try to fold the OpSpecConstantOp CompositeExtract instruction pointed by
+  // the given instruction iterator to a normal constant defining instruction.
+  // Returns the pointer to the new constant defining instruction if succeeded.
+  // Otherwise returns nullptr.
+  ir::Instruction* DoCompositeExtract(ir::Module::inst_iterator* inst_iter_ptr);
+
+  // Try to fold the OpSpecConstantOp VectorShuffle instruction pointed by the
+  // given instruction iterator to a normal constant defining instruction.
+  // Returns the pointer to the new constant defining instruction if succeeded.
+  // Otherwise return nullptr.
+  ir::Instruction* DoVectorShuffle(ir::Module::inst_iterator* inst_iter_ptr);
+
+  // Try to fold the OpSpecConstantOp <component wise operations> instruction
+  // pointed by the given instruction iterator to a normal constant defining
+  // instruction. Returns the pointer to the new constant defining instruction
+  // if succeeded, otherwise return nullptr.
+  ir::Instruction* DoComponentWiseOperation(
+      ir::Module::inst_iterator* inst_iter_ptr);
+
+  // Creates a constant defining instruction for the given Constant instance
+  // and inserts the instruction at the position specified by the given
+  // instruction iterator. Returns a pointer to the created instruction if
+  // succeeded, otherwise returns a null pointer. The instruction iterator
+  // points to the same instruction before and after the insertion. This is the
+  // only method that actually manages id creation/assignment and instruction
+  // creation/insertion for a new Constant instance.
+  ir::Instruction* BuildInstructionAndAddToModule(
+      std::unique_ptr<analysis::Constant> c, ir::Module::inst_iterator* pos);
+
+  // Creates a Constant instance to hold the constant value of the given
+  // instruction. If the given instruction defines a normal constants whose
+  // value is already known in the module, returns the unique pointer to the
+  // created Constant instance. Otherwise does not create anything and returns a
+  // nullptr.
+  std::unique_ptr<analysis::Constant> CreateConstFromInst(
+      ir::Instruction* inst);
+
+  // Creates a Constant instance with the given type and a vector of constant
+  // defining words. Returns an unique pointer to the created Constant instance
+  // if the Constant instance can be created successfully. To create scalar
+  // type constants, the vector should contain the constant value in 32 bit
+  // words and the given type must be of type Bool, Integer or Float. To create
+  // composite type constants, the vector should contain the component ids, and
+  // those component ids should have been recorded before as Normal Constants.
+  // And the given type must be of type Struct, Vector or Array. When creating
+  // VectorType Constant instance, the components must be scalars of the same
+  // type, either Bool, Integer or Float. If any of the rules above failed, the
+  // creation will fail and nullptr will be returned. If the vector is empty,
+  // a NullConstant instance will be created with the given type.
+  std::unique_ptr<analysis::Constant> CreateConst(
+      const analysis::Type* type,
+      const std::vector<uint32_t>& literal_words_or_ids);
+
+  // Creates an instruction with the given result id to declare a constant
+  // represented by the given Constant instance. Returns an unique pointer to
+  // the created instruction if the instruction can be created successfully.
+  // Otherwise, returns a null pointer.
+  std::unique_ptr<ir::Instruction> CreateInstruction(uint32_t result_id,
+                                                     analysis::Constant* c);
+
+  // Creates an OpConstantComposite instruction with the given result id and
+  // the CompositeConst instance which represents a composite constant. Returns
+  // an unique pointer to the created instruction if succeeded. Otherwise
+  // returns a null pointer.
+  std::unique_ptr<ir::Instruction> CreateCompositeInstruction(
+      uint32_t result_id, analysis::CompositeConstant* cc);
+
+  // A helper function to get the collected normal constant with the given id.
+  // Returns the pointer to the Constant instance in case it is found.
+  // Otherwise, returns null pointer.
+  analysis::Constant* FindRecordedConst(uint32_t id);
+  // A helper function to get the id of a collected constant with the pointer
+  // to the Constant instance. Returns 0 in case the constant is not found.
+  uint32_t FindRecordedConst(const analysis::Constant* c);
+
+  // A helper function to get a vector of Constant instances with the specified
+  // ids. If can not find the Constant instance for any one of the ids, returns
+  // an empty vector.
+  std::vector<const analysis::Constant*> GetConstsFromIds(
+      const std::vector<uint32_t>& ids);
+
+  // A helper function to get the result type of the given instrution. Returns
+  // nullptr if the instruction does not have a type id (type id is 0).
+  analysis::Type* GetType(const ir::Instruction* inst) {
+    return type_mgr_->GetType(inst->type_id());
+  }
+
+  // The maximum used ID.
+  uint32_t max_id_;
+  // A pointer to the module under process.
+  ir::Module* module_;
+  // DefUse manager
+  std::unique_ptr<analysis::DefUseManager> def_use_mgr_;
+  // Type manager
+  std::unique_ptr<analysis::TypeManager> type_mgr_;
+
+  // A mapping from the result ids of Normal Constants to their
+  // analysis::Constant instances. All Normal Constants in the module, either
+  // existing ones before optimization or the newly generated ones, should have
+  // their Constant instance stored and their result id registered in this map.
+  std::unordered_map<uint32_t, std::unique_ptr<analysis::Constant>>
+      id_to_const_val_;
+  // A mapping from the analsis::Constant instance of Normal Contants to their
+  // result id in the module. This is a mirror map of id_to_const_val_. All
+  // Normal Constants that defining instructions in the module should have
+  // their analysis::Constant and their result id registered here.
+  std::unordered_map<const analysis::Constant*, uint32_t> const_val_to_id_;
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // LIBSPIRV_OPT_FOLD_SPEC_CONSTANT_OP_AND_COMPOSITE_PASS_H_
diff --git a/source/opt/freeze_spec_constant_value_pass.cpp b/source/opt/freeze_spec_constant_value_pass.cpp
new file mode 100644
index 0000000..a735aaf
--- /dev/null
+++ b/source/opt/freeze_spec_constant_value_pass.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "freeze_spec_constant_value_pass.h"
+
+namespace spvtools {
+namespace opt {
+
+bool FreezeSpecConstantValuePass::Process(ir::Module* module) {
+  bool modified = false;
+  module->ForEachInst([&modified](ir::Instruction* inst) {
+    switch (inst->opcode()) {
+      case SpvOp::SpvOpSpecConstant:
+        inst->SetOpcode(SpvOp::SpvOpConstant);
+        modified = true;
+        break;
+      case SpvOp::SpvOpSpecConstantTrue:
+        inst->SetOpcode(SpvOp::SpvOpConstantTrue);
+        modified = true;
+        break;
+      case SpvOp::SpvOpSpecConstantFalse:
+        inst->SetOpcode(SpvOp::SpvOpConstantFalse);
+        modified = true;
+        break;
+      case SpvOp::SpvOpDecorate:
+        if (inst->GetSingleWordInOperand(1) ==
+            SpvDecoration::SpvDecorationSpecId) {
+          inst->ToNop();
+          modified = true;
+        }
+        break;
+      default:
+        break;
+    }
+  });
+  return modified;
+}
+
+}  // namespace opt
+}  // namespace spvtools
diff --git a/source/opt/freeze_spec_constant_value_pass.h b/source/opt/freeze_spec_constant_value_pass.h
new file mode 100644
index 0000000..e662b97
--- /dev/null
+++ b/source/opt/freeze_spec_constant_value_pass.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef LIBSPIRV_OPT_FREEZE_SPEC_CONSTANT_VALUE_PASS_H_
+#define LIBSPIRV_OPT_FREEZE_SPEC_CONSTANT_VALUE_PASS_H_
+
+#include "module.h"
+#include "pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// The transformation pass that specializes the value of spec constants to
+// their default values. This pass only processes the spec constants that have
+// Spec ID decorations (defined by OpSpecConstant, OpSpecConstantTrue and
+// OpSpecConstantFalse instructions) and replaces them with their front-end
+// version counterparts (OpConstant, OpConstantTrue and OpConstantFalse). The
+// corresponding Spec ID annotation instructions will also be removed. This
+// pass does not fold the newly added front-end constants and does not process
+// other spec constants defined by OpSpecConstantComposite or OpSpecConstantOp.
+class FreezeSpecConstantValuePass : public Pass {
+ public:
+  const char* name() const override { return "freeze-spec-const"; }
+  bool Process(ir::Module*) override;
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // LIBSPIRV_OPT_FREEZE_SPEC_CONSTANT_VALUE_PASS_H_
diff --git a/source/opt/null_pass.h b/source/opt/null_pass.h
new file mode 100644
index 0000000..5c00e99
--- /dev/null
+++ b/source/opt/null_pass.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef LIBSPIRV_OPT_NULL_PASS_H_
+#define LIBSPIRV_OPT_NULL_PASS_H_
+
+#include "module.h"
+#include "pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// A null pass that does nothing.
+class NullPass : public Pass {
+  const char* name() const override { return "null"; }
+  bool Process(ir::Module*) override { return false; }
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // LIBSPIRV_OPT_NULL_PASS_H_
diff --git a/source/opt/passes.h b/source/opt/passes.h
index f742666..2e3d738 100644
--- a/source/opt/passes.h
+++ b/source/opt/passes.h
@@ -27,232 +27,12 @@
 #ifndef LIBSPIRV_OPT_PASSES_H_
 #define LIBSPIRV_OPT_PASSES_H_
 
-#include <algorithm>
-#include <memory>
-#include <unordered_map>
-#include <vector>
+// A single header to include all passes.
 
-#include "constants.h"
-#include "def_use_manager.h"
-#include "module.h"
-#include "pass.h"
-#include "type_manager.h"
-
-namespace spvtools {
-namespace opt {
-
-// A null pass that does nothing.
-class NullPass : public Pass {
-  const char* name() const override { return "null"; }
-  bool Process(ir::Module*) override { return false; }
-};
-
-// The optimization pass for removing debug instructions (as documented in
-// Section 3.32.2 of the SPIR-V spec).
-class StripDebugInfoPass : public Pass {
- public:
-  const char* name() const override { return "strip-debug"; }
-  bool Process(ir::Module* module) override;
-};
-
-// The transformation pass that specializes the value of spec constants to
-// their default values. This pass only processes the spec constants that have
-// Spec ID decorations (defined by OpSpecConstant, OpSpecConstantTrue and
-// OpSpecConstantFalse instructions) and replaces them with their front-end
-// version counterparts (OpConstant, OpConstantTrue and OpConstantFalse). The
-// corresponding Spec ID annotation instructions will also be removed. This
-// pass does not fold the newly added front-end constants and does not process
-// other spec constants defined by OpSpecConstantComposite or OpSpecConstantOp.
-class FreezeSpecConstantValuePass : public Pass {
- public:
-  const char* name() const override { return "freeze-spec-const"; }
-  bool Process(ir::Module*) override;
-};
-
-// The optimization pass to remove dead constants, including front-end
-// contants: defined by OpConstant, OpConstantComposite, OpConstantTrue and
-// OpConstantFalse; and spec constants: defined by OpSpecConstant,
-// OpSpecConstantComposite, OpSpecConstantTrue, OpSpecConstantFalse and
-// OpSpecConstantOp.
-class EliminateDeadConstantPass : public Pass {
- public:
-  const char* name() const override { return "eliminate-dead-const"; }
-  bool Process(ir::Module*) override;
-};
-
-// The optimization pass that folds "Spec Constants", which are defined by
-// OpSpecConstantOp and OpSpecConstantComposite instruction, to "Normal
-// Constants", which are defined by OpConstantTrue, OpConstantFalse,
-// OpConstant, OpConstantNull and OpConstantComposite instructions. Note that
-// Spec Constants defined with OpSpecConstant, OpSpecConstantTrue and
-// OpSpecConstantFalse instructions are not handled, as these instructions
-// indicate their value are not determined and can be changed in future.  A
-// Spec Constant is foldable if all of its value(s) can be determined from the
-// module. For example, an Integer Spec Constant defined with OpSpecConstantOp
-// instruction can be folded if its value won't change later. This pass will
-// replace the original OpSpecContantOp instruction with an OpConstant
-// instruction. When folding composite type Spec Constants, new instructions
-// may be inserted to define the components of the composite constant first,
-// then the original Spec Constants will be replace with OpConstantComposite
-// instructions.
-// There are some operations not supported:
-//  OpSConvert, OpFConvert, OpQuantizeToF16 and all the operations under Kernel
-//  capability.
-// TODO(qining): Add support for the operations listed above.
-class FoldSpecConstantOpAndCompositePass : public Pass {
- public:
-  FoldSpecConstantOpAndCompositePass()
-      : max_id_(0),
-        module_(nullptr),
-        def_use_mgr_(nullptr),
-        type_mgr_(nullptr),
-        id_to_const_val_() {}
-  const char* name() const override { return "fold-spec-const-op-composite"; }
-  bool Process(ir::Module* module) override {
-    Initialize(module);
-    return ProcessImpl(module);
-  };
-
- private:
-  // Initializes the type manager, def-use manager and get the maximal id used
-  // in the module.
-  void Initialize(ir::Module* module) {
-    type_mgr_.reset(new analysis::TypeManager(*module));
-    def_use_mgr_.reset(new analysis::DefUseManager(module));
-    for (const auto& id_def : def_use_mgr_->id_to_defs()) {
-      max_id_ = std::max(max_id_, id_def.first);
-    }
-    module_ = module;
-  };
-
-  // The real entry of processing. Iterates through the types-constants-globals
-  // section of the given module, finds the Spec Constants defined with
-  // OpSpecConstantOp and OpSpecConstantComposite instructions. If the result
-  // value of those spec constants can be folded, fold them to their
-  // corresponding normal constants. Returns true if the module was modified.
-  bool ProcessImpl(ir::Module*);
-
-  // Processes the OpSpecConstantOp instruction pointed by the given
-  // instruction iterator, folds it to normal constants if possible. Returns
-  // true if the spec constant is folded to normal constants. New instructions
-  // will be inserted before the OpSpecConstantOp instruction pointed by the
-  // instruction iterator. The instruction iterator, which is passed by
-  // pointer, will still point to the original OpSpecConstantOp instruction. If
-  // folding is done successfully, the original OpSpecConstantOp instruction
-  // will be changed to Nop and new folded instruction will be inserted before
-  // it.
-  bool ProcessOpSpecConstantOp(ir::Module::inst_iterator* pos);
-
-  // Try to fold the OpSpecConstantOp CompositeExtract instruction pointed by
-  // the given instruction iterator to a normal constant defining instruction.
-  // Returns the pointer to the new constant defining instruction if succeeded.
-  // Otherwise returns nullptr.
-  ir::Instruction* DoCompositeExtract(ir::Module::inst_iterator* inst_iter_ptr);
-
-  // Try to fold the OpSpecConstantOp VectorShuffle instruction pointed by the
-  // given instruction iterator to a normal constant defining instruction.
-  // Returns the pointer to the new constant defining instruction if succeeded.
-  // Otherwise return nullptr.
-  ir::Instruction* DoVectorShuffle(ir::Module::inst_iterator* inst_iter_ptr);
-
-  // Try to fold the OpSpecConstantOp <component wise operations> instruction
-  // pointed by the given instruction iterator to a normal constant defining
-  // instruction. Returns the pointer to the new constant defining instruction
-  // if succeeded, otherwise return nullptr.
-  ir::Instruction* DoComponentWiseOperation(
-      ir::Module::inst_iterator* inst_iter_ptr);
-
-  // Creates a constant defining instruction for the given Constant instance
-  // and inserts the instruction at the position specified by the given
-  // instruction iterator. Returns a pointer to the created instruction if
-  // succeeded, otherwise returns a null pointer. The instruction iterator
-  // points to the same instruction before and after the insertion. This is the
-  // only method that actually manages id creation/assignment and instruction
-  // creation/insertion for a new Constant instance.
-  ir::Instruction* BuildInstructionAndAddToModule(
-      std::unique_ptr<analysis::Constant> c, ir::Module::inst_iterator* pos);
-
-  // Creates a Constant instance to hold the constant value of the given
-  // instruction. If the given instruction defines a normal constants whose
-  // value is already known in the module, returns the unique pointer to the
-  // created Constant instance. Otherwise does not create anything and returns a
-  // nullptr.
-  std::unique_ptr<analysis::Constant> CreateConstFromInst(
-      ir::Instruction* inst);
-
-  // Creates a Constant instance with the given type and a vector of constant
-  // defining words. Returns an unique pointer to the created Constant instance
-  // if the Constant instance can be created successfully. To create scalar
-  // type constants, the vector should contain the constant value in 32 bit
-  // words and the given type must be of type Bool, Integer or Float. To create
-  // composite type constants, the vector should contain the component ids, and
-  // those component ids should have been recorded before as Normal Constants.
-  // And the given type must be of type Struct, Vector or Array. When creating
-  // VectorType Constant instance, the components must be scalars of the same
-  // type, either Bool, Integer or Float. If any of the rules above failed, the
-  // creation will fail and nullptr will be returned. If the vector is empty,
-  // a NullConstant instance will be created with the given type.
-  std::unique_ptr<analysis::Constant> CreateConst(
-      const analysis::Type* type,
-      const std::vector<uint32_t>& literal_words_or_ids);
-
-  // Creates an instruction with the given result id to declare a constant
-  // represented by the given Constant instance. Returns an unique pointer to
-  // the created instruction if the instruction can be created successfully.
-  // Otherwise, returns a null pointer.
-  std::unique_ptr<ir::Instruction> CreateInstruction(uint32_t result_id,
-                                                     analysis::Constant* c);
-
-  // Creates an OpConstantComposite instruction with the given result id and
-  // the CompositeConst instance which represents a composite constant. Returns
-  // an unique pointer to the created instruction if succeeded. Otherwise
-  // returns a null pointer.
-  std::unique_ptr<ir::Instruction> CreateCompositeInstruction(
-      uint32_t result_id, analysis::CompositeConstant* cc);
-
-  // A helper function to get the collected normal constant with the given id.
-  // Returns the pointer to the Constant instance in case it is found.
-  // Otherwise, returns null pointer.
-  analysis::Constant* FindRecordedConst(uint32_t id);
-  // A helper function to get the id of a collected constant with the pointer
-  // to the Constant instance. Returns 0 in case the constant is not found.
-  uint32_t FindRecordedConst(const analysis::Constant* c);
-
-  // A helper function to get a vector of Constant instances with the specified
-  // ids. If can not find the Constant instance for any one of the ids, returns
-  // an empty vector.
-  std::vector<const analysis::Constant*> GetConstsFromIds(
-      const std::vector<uint32_t>& ids);
-
-  // A helper function to get the result type of the given instrution. Returns
-  // nullptr if the instruction does not have a type id (type id is 0).
-  analysis::Type* GetType(const ir::Instruction* inst) {
-    return type_mgr_->GetType(inst->type_id());
-  }
-
-  // The maximum used ID.
-  uint32_t max_id_;
-  // A pointer to the module under process.
-  ir::Module* module_;
-  // DefUse manager
-  std::unique_ptr<analysis::DefUseManager> def_use_mgr_;
-  // Type manager
-  std::unique_ptr<analysis::TypeManager> type_mgr_;
-
-  // A mapping from the result ids of Normal Constants to their
-  // analysis::Constant instances. All Normal Constants in the module, either
-  // existing ones before optimization or the newly generated ones, should have
-  // their Constant instance stored and their result id registered in this map.
-  std::unordered_map<uint32_t, std::unique_ptr<analysis::Constant>>
-      id_to_const_val_;
-  // A mapping from the analsis::Constant instance of Normal Contants to their
-  // result id in the module. This is a mirror map of id_to_const_val_. All
-  // Normal Constants that defining instructions in the module should have
-  // their analysis::Constant and their result id registered here.
-  std::unordered_map<const analysis::Constant*, uint32_t> const_val_to_id_;
-};
-
-}  // namespace opt
-}  // namespace spvtools
+#include "eliminate_dead_constant_pass.h"
+#include "fold_spec_constant_op_and_composite_pass.h"
+#include "freeze_spec_constant_value_pass.h"
+#include "null_pass.h"
+#include "strip_debug_info_pass.h"
 
 #endif  // LIBSPIRV_OPT_PASSES_H_
diff --git a/source/opt/strip_debug_info_pass.cpp b/source/opt/strip_debug_info_pass.cpp
new file mode 100644
index 0000000..3b75811
--- /dev/null
+++ b/source/opt/strip_debug_info_pass.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#include "strip_debug_info_pass.h"
+
+namespace spvtools {
+namespace opt {
+
+bool StripDebugInfoPass::Process(ir::Module* module) {
+  bool modified = !module->debugs().empty();
+  module->debug_clear();
+
+  module->ForEachInst([&modified](ir::Instruction* inst) {
+    modified |= !inst->dbg_line_insts().empty();
+    inst->dbg_line_insts().clear();
+  });
+
+  return modified;
+}
+
+}  // namespace opt
+}  // namespace spvtools
diff --git a/source/opt/strip_debug_info_pass.h b/source/opt/strip_debug_info_pass.h
new file mode 100644
index 0000000..1587f3d
--- /dev/null
+++ b/source/opt/strip_debug_info_pass.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Materials.
+//
+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
+//    https://www.khronos.org/registry/
+//
+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+#ifndef LIBSPIRV_OPT_STRIP_DEBUG_INFO_PASS_H_
+#define LIBSPIRV_OPT_STRIP_DEBUG_INFO_PASS_H_
+
+#include "module.h"
+#include "pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// The optimization pass for removing debug instructions (as documented in
+// Section 3.32.2 of the SPIR-V spec).
+class StripDebugInfoPass : public Pass {
+ public:
+  const char* name() const override { return "strip-debug"; }
+  bool Process(ir::Module* module) override;
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // LIBSPIRV_OPT_STRIP_DEBUG_INFO_PASS_H_