Explorar o código

+ 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 %!s(int64=9) %!d(string=hai) anos
pai
achega
b4fe4789d6
Modificáronse 4 ficheiros con 54 adicións e 25 borrados
  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_FPUREGISTER,
         LOC_MMREGISTER: (reg: tregister);
+        LOC_CONSTANT: (value: tcgint);
     end;
 
 

+ 2 - 0
compiler/llvm/agllvm.pas

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

+ 50 - 25
compiler/llvm/hlcgllvm.pas

@@ -42,6 +42,7 @@ uses
       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_const_cgpara(list: TAsmList; tosize: tdef; a: tcgint; const cgpara: TCGPara); override;
      protected
        procedure a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
      public
@@ -278,6 +279,22 @@ implementation
     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);
     var
       newrefsize: tdef;
@@ -379,36 +396,44 @@ implementation
             new(callpara);
             callpara^.def:=paraloc^.def;
             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
-                      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;
-                  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
-                      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;
-                    callpara^.reg:=paraloc^.register
+                  else
+                    internalerror(2014010605);
                 end;
-              else
-                internalerror(2014010605);
-            end;
+              end;
             callparas.add(callpara);
             paraloc:=paraloc^.next;
           end;

+ 1 - 0
compiler/parabase.pas

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