Jelajahi Sumber

+ support for constant call parameters on LLVM
o reduces the size of the generated LLVM IR, but mainly important for LLVM
intrinsics such as llvm.memcpy.*(), as llc complains if some of their
parameters are not constants (you could work around it by first running
opt or by using clang with optimizations so that the constants, which
were loaded in registers until now, were propagated to the intrinsics
by the time llc saw them)

git-svn-id: trunk@32776 -

Jonas Maebe 9 tahun lalu
induk
melakukan
b4fe4789d6
4 mengubah file dengan 54 tambahan dan 25 penghapusan
  1. 1 0
      compiler/llvm/aasmllvm.pas
  2. 2 0
      compiler/llvm/agllvm.pas
  3. 50 25
      compiler/llvm/hlcgllvm.pas
  4. 1 0
      compiler/parabase.pas

+ 1 - 0
compiler/llvm/aasmllvm.pas

@@ -185,6 +185,7 @@ interface
         LOC_REGISTER,
         LOC_REGISTER,
         LOC_FPUREGISTER,
         LOC_FPUREGISTER,
         LOC_MMREGISTER: (reg: tregister);
         LOC_MMREGISTER: (reg: tregister);
+        LOC_CONSTANT: (value: tcgint);
     end;
     end;
 
 
 
 

+ 2 - 0
compiler/llvm/agllvm.pas

@@ -246,6 +246,8 @@ implementation
              LOC_FPUREGISTER,
              LOC_FPUREGISTER,
              LOC_MMREGISTER:
              LOC_MMREGISTER:
                result:=result+' '+getregisterstring(para^.reg);
                result:=result+' '+getregisterstring(para^.reg);
+             LOC_CONSTANT:
+               result:=result+' '+tostr(int64(para^.value));
              else
              else
                internalerror(2014010801);
                internalerror(2014010801);
            end;
            end;

+ 50 - 25
compiler/llvm/hlcgllvm.pas

@@ -42,6 +42,7 @@ uses
       procedure temp_to_ref(p: ptemprecord; out ref: treference); override;
       procedure temp_to_ref(p: ptemprecord; out ref: treference); override;
 
 
       procedure a_load_ref_cgpara(list: TAsmList; size: tdef; const r: treference; const cgpara: TCGPara); override;
       procedure a_load_ref_cgpara(list: TAsmList; size: tdef; const r: treference; const cgpara: TCGPara); override;
+      procedure a_load_const_cgpara(list: TAsmList; tosize: tdef; a: tcgint; const cgpara: TCGPara); override;
      protected
      protected
        procedure a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
        procedure a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
      public
      public
@@ -278,6 +279,22 @@ implementation
     end;
     end;
 
 
 
 
+  procedure thlcgllvm.a_load_const_cgpara(list: TAsmList; tosize: tdef; a: tcgint; const cgpara: TCGPara);
+    begin
+      if is_ordinal(cgpara.def) then
+        begin
+          cgpara.check_simple_location;
+          paramanager.alloccgpara(list,cgpara);
+          if cgpara.location^.shiftval<0 then
+            a:=a shl -cgpara.location^.shiftval;
+          cgpara.location^.llvmloc.loc:=LOC_CONSTANT;
+          cgpara.location^.llvmloc.value:=a;
+        end
+      else
+        inherited;
+    end;
+
+
   procedure thlcgllvm.a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
   procedure thlcgllvm.a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
     var
     var
       newrefsize: tdef;
       newrefsize: tdef;
@@ -379,36 +396,44 @@ implementation
             new(callpara);
             new(callpara);
             callpara^.def:=paraloc^.def;
             callpara^.def:=paraloc^.def;
             llvmextractvalueextinfo(paras[i]^.def, callpara^.def, callpara^.valueext);
             llvmextractvalueextinfo(paras[i]^.def, callpara^.def, callpara^.valueext);
-            callpara^.loc:=paraloc^.loc;
-            case callpara^.loc of
-              LOC_REFERENCE:
-                begin
-                  if paraloc^.llvmvalueloc then
-                    internalerror(2014012307)
-                  else
+            if paraloc^.llvmloc.loc=LOC_CONSTANT then
+              begin
+                callpara^.loc:=LOC_CONSTANT;
+                callpara^.value:=paraloc^.llvmloc.value;
+              end
+            else
+              begin
+                callpara^.loc:=paraloc^.loc;
+                case callpara^.loc of
+                  LOC_REFERENCE:
                     begin
                     begin
-                      reference_reset_base(href, cpointerdef.getreusable(callpara^.def), paraloc^.reference.index, paraloc^.reference.offset, paraloc^.def.alignment);
-                      res:=getregisterfordef(list, paraloc^.def);
-                      load_ref_anyreg(callpara^.def, href, res, callpara);
+                      if paraloc^.llvmvalueloc then
+                        internalerror(2014012307)
+                      else
+                        begin
+                          reference_reset_base(href, cpointerdef.getreusable(callpara^.def), paraloc^.reference.index, paraloc^.reference.offset, paraloc^.def.alignment);
+                          res:=getregisterfordef(list, paraloc^.def);
+                          load_ref_anyreg(callpara^.def, href, res, callpara);
+                        end;
+                      callpara^.reg:=res
                     end;
                     end;
-                  callpara^.reg:=res
-                end;
-              LOC_REGISTER,
-              LOC_FPUREGISTER,
-              LOC_MMREGISTER:
-                begin
-                  { undo explicit value extension }
-                  if callpara^.valueext<>lve_none then
+                  LOC_REGISTER,
+                  LOC_FPUREGISTER,
+                  LOC_MMREGISTER:
                     begin
                     begin
-                      res:=getregisterfordef(list, callpara^.def);
-                      a_load_reg_reg(list, paraloc^.def, callpara^.def, paraloc^.register, res);
-                      paraloc^.register:=res;
+                      { undo explicit value extension }
+                      if callpara^.valueext<>lve_none then
+                        begin
+                          res:=getregisterfordef(list, callpara^.def);
+                          a_load_reg_reg(list, paraloc^.def, callpara^.def, paraloc^.register, res);
+                          paraloc^.register:=res;
+                        end;
+                        callpara^.reg:=paraloc^.register
                     end;
                     end;
-                    callpara^.reg:=paraloc^.register
+                  else
+                    internalerror(2014010605);
                 end;
                 end;
-              else
-                internalerror(2014010605);
-            end;
+              end;
             callparas.add(callpara);
             callparas.add(callpara);
             paraloc:=paraloc^.next;
             paraloc:=paraloc^.next;
           end;
           end;

+ 1 - 0
compiler/parabase.pas

@@ -60,6 +60,7 @@ unit parabase;
                if llvmvalueloc=false: must be a tempreg. Means that the value is
                if llvmvalueloc=false: must be a tempreg. Means that the value is
                stored in a temp with this register as base address }
                stored in a temp with this register as base address }
              LOC_REGISTER:  (reg: tregister);
              LOC_REGISTER:  (reg: tregister);
+             LOC_CONSTANT:  (value: tcgint);
          end;
          end;
 {$endif llvm}
 {$endif llvm}
          case TCGLoc of
          case TCGLoc of